[英]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.