簡體   English   中英

如何在自定義控件中對列表屬性進行綁定工作?

[英]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 如果強制轉換無效,並且將其發送為nullViewModel屬性。

在那里,當您將類型設置為IEnumerable<string>您將已將SelectedItemsstring集合,例如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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM