附加到视图模型的数据绑定 属性 失败

Data binding attached property to view model fails

我为 ListBox 创建了一个附加的 属性,如下所示:

using ListBoxControl = System.Windows.Controls.ListBox;

namespace App.Ui.Views.AttachedProperties
{
    public class ListBox
    {
        public static readonly DependencyProperty autoScrollProperty =
            DependencyProperty.RegisterAttached(
                "AutoScroll", 
                typeof(bool), 
                typeof(ListBoxControl), 
                new PropertyMetadata(false));

        public static void SetAutoScroll(ListBoxControl element, bool value)
        {
            element.SetValue(autoScrollProperty, value);
            if (value)
            {
                element.SelectionChanged += Element_SelectionChanged;
            }
            else
            {
                element.SelectionChanged -= Element_SelectionChanged;
            }
        }

        public static bool GetAutoScroll(ListBoxControl element)
        {
            return (bool)element.GetValue(autoScrollProperty);
        }

        private static void Element_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var listBox = (ListBoxControl)sender;
            listBox.ScrollIntoView(listBox.SelectedItem);
        }
    }
}

当我在 xaml 中使用静态 True/False 值时,它工作正常:

<ListBox ap:ListBox.AutoScroll="True">
    ...
</ListBox>

但是如果我在视图模型中将数据绑定到 属性:

<ListBox ap:ListBox.AutoScroll="{Binding Path=Settings.EnableAutoScroll}">
    ...
</ListBox>

然后我得到以下异常:A 'Binding' cannot be set on the 'SetAutoScroll' property of type 'ListBox'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject.

这可能吗,还是我需要派生自己的自定义列表框才能完成此操作?

这一行有问题typeof(ListBoxControl)。您应该指定自定义附加 属性 席位的 class 的名称。

我建议将 class 从 ListBox 重命名为 ListBoxExtensions,同时将其设为静态。这样您就不必使用别名 ListBoxControl。
您的最终代码将如下所示:

public static class ListBoxExtensions
{
    public static readonly DependencyProperty autoScrollProperty =
                DependencyProperty.RegisterAttached(
                    "AutoScroll", 
                    typeof(bool), 
                    typeof(ListBoxExtensions), 
                    new PropertyMetadata(false));

      ...
}

编辑: 好的,您的代码还有另一个问题。
从 setter (SetAutoScroll) 中删除监听器的附件并将此逻辑放入依赖项 属性 回调中。

public static class ListBoxExtensions
{
    public static readonly DependencyProperty autoScrollProperty =
        DependencyProperty.RegisterAttached(
            "AutoScroll",
            typeof(bool),
            typeof(ListBoxExtensions),
            new PropertyMetadata(false, AutoScrollChangedCallback));

    public static void SetAutoScroll(ListBox element, bool value)
    {
        element.SetValue(autoScrollProperty, value);
    }

    public static bool GetAutoScroll(ListBox element)
    {
        return (bool)element.GetValue(autoScrollProperty);
    }

    private static void AutoScrollChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        ListBox control = (ListBox)d;

        if ((bool)e.NewValue)
        {
            control.SelectionChanged += Element_SelectionChanged;
        }
        else
        {
            control.SelectionChanged -= Element_SelectionChanged;
        }
    }

    private static void Element_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        var listBox = (ListBox)sender;
        listBox.ScrollIntoView(listBox.SelectedItem);
    }
}