[英]How do I make binding work for a list property in a custom control?
由于ListBox
不允许您双向绑定到其SelectedItems
属性,因此我创建了自己的自定义控件MultipleSelectionListBox
。 它添加了属性BindableSelectedItems
,使您可以将IEnumerable
绑定到它。
public class MultipleSelectionListBox : ListBox
{
public static readonly DependencyProperty BindableSelectedItemsProperty =
DependencyProperty.Register("BindableSelectedItems",
typeof(IEnumerable), typeof(MultipleSelectionListBox),
new FrameworkPropertyMetadata(default(IEnumerable),
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnBindableSelectedItemsChanged));
public IEnumerable BindableSelectedItems
{
get => (IEnumerable)GetValue(BindableSelectedItemsProperty);
set => SetValue(BindableSelectedItemsProperty, value);
}
protected override void OnSelectionChanged(SelectionChangedEventArgs e)
{
base.OnSelectionChanged(e);
BindableSelectedItems = SelectedItems;
}
private static void OnBindableSelectedItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is MultipleSelectionListBox listBox)
listBox.SetSelectedItems(listBox.BindableSelectedItems);
}
}
我绑定到的视图模型的属性的类型为IEnumerable<string>
,并且绑定不起作用。 更改列表框的选择时,视图模型的属性始终接收null
。
如果我将BindableSelectedItems
的类型更改为IEnumerable<string>
,则绑定有效。 这使我相信绑定不喜欢类型不匹配。 我是否必须明确指定列表项的类型,还是可以保持列表的一般性? 能够对其他类型的项目使用相同的MultipleSelectionListBox
会很好。
这是因为SelectedItems
的类型始终为System.Collections.IList {System.Windows.Controls.SelectedItemCollection}
。 因此,当您尝试使用IEnumerable
您直接将SelectedItems
分配给BindableSelectedItems
。 如果强制转换无效,并且将其发送为null
到ViewModel
属性。
在那里,当您将类型设置为IEnumerable<string>
您将已将SelectedItems
为string
集合,例如BindableSelectedItems = SelectedItems.Cast<string>();
它与ViewModel
中的属性类型匹配并且有效。
我看到您想使其通用。 为此,您可以尝试类似的方法,
列表框控件代码
public class MultipleSelectionListBox : ListBox
{
public static readonly DependencyProperty BindableSelectedItemsProperty =
DependencyProperty.Register("BindableSelectedItems",
typeof(IList), typeof(MultipleSelectionListBox),
new FrameworkPropertyMetadata(default(IList),
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnBindableSelectedItemsChanged));
public IList BindableSelectedItems
{
get => (IList)GetValue(BindableSelectedItemsProperty);
set => SetValue(BindableSelectedItemsProperty, value);
}
protected override void OnSelectionChanged(SelectionChangedEventArgs e)
{
base.OnSelectionChanged(e);
IList selectedItemsList = BindableSelectedItems;
if (selectedItemsList == null)
selectedItemsList = (IList)Activator.CreateInstance(ItemsSource.GetType());
selectedItemsList.Clear();
foreach (var item in SelectedItems)
selectedItemsList.Add(item);
BindableSelectedItems = selectedItemsList;
}
private static void OnBindableSelectedItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is MultipleSelectionListBox listBox)
listBox.SetSelectedItems(listBox.BindableSelectedItems);
}
}
视图模型
public class ViewModel
{
public IEnumerable Items { get; set; }
public IEnumerable SelectedItems { get; set; }
public ViewModel()
{
Items = new List<string> { "Test", "Test1" };
SelectedItems = new List<string> { "Test" };
}
}
我已经测试了常见的情况,并且工作正常。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.