c# - Data binding attached property to view model fails
问题描述
I created an attached property for ListBox like this:
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);
}
}
}
When I use a static True/False value in the xaml, it works fine:
<ListBox ap:ListBox.AutoScroll="True">
...
</ListBox>
But if I data bind to a property in my view model:
<ListBox ap:ListBox.AutoScroll="{Binding Path=Settings.EnableAutoScroll}">
...
</ListBox>
Then I get the following exception: A 'Binding' cannot be set on the 'SetAutoScroll' property of type 'ListBox'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject.
Is this possible, or am I going to need to derive my own custom list box to accomplish this?
解决方案
这一行有问题typeof(ListBoxControl)
。您应该指定自定义附加属性所在的类的名称。
我建议将类从 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);
}
}
推荐阅读
- c++ - 使用 Unity 插件的 EntryPointNotFoundException
- c++ - 用户输入到 C++ 中的数组列表
- python - 为什么在模式/弹出窗口上滚动在 Instagram 上不起作用
- android - Android 任务 :app:lint - 运行时 JAR 文件的版本比 API 版本所需的版本旧
- r - 改变森林地块 R 中正方形的大小
- javascript - 将 json 对象转换为 csv 文件并使用 JSZip 合并它们
- arrays - React - 当我尝试在其他地方声明它时,我的数组组件上的映射函数没有定义
- linux - Httpd (Apache) 不刷新站点
- javascript - 如何按权限过滤路由数组?
- c++ - 没有规则使 src/exe/rookery_exe 需要目标 src/core/librookery_core.a