由于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
用于其他类型的项目会很好。
答案 0 :(得分:1)
这是因为SelectedItems
将始终为System.Collections.IList {System.Windows.Controls.SelectedItemCollection}
类型。因此,当您尝试使用IEnumerable
时,您是直接将SelectedItems
分配给BindableSelectedItems
。在强制转换无效的情况下,它已null
发送到您的ViewModel
属性。
当您将类型设置为IEnumerable<string>
时,您会将SelectedItems
强制转换为string
之类的BindableSelectedItems = SelectedItems.Cast<string>();
集合,该集合与{{ 1}}并有效。
我看到您想使其通用。为此,您可以尝试类似的
列表框控件代码
ViewModel
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);
}
}
我已经在常见情况下进行了测试,并且工作正常。