首页 > 解决方案 > 从静态依赖属性类中的 OnCollectionChanged 方法更新控制器

问题描述

我正在尝试创建一个dependency property允许我以两种方式将其选定项目的数据网格绑定到我的视图模型中的属性。

到目前为止,我让它以一种方式工作,当在数据网格中更改所选项目时,我的集合被更新,但这就是我遇到障碍的地方

public static class MultiSelectorHelper
{
    public static readonly DependencyProperty SelectedItemsProperty = DependencyProperty.RegisterAttached(
        "SelectedItems",
        typeof(IList),
        typeof(MultiSelectorHelper),
        new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnSelectedItemsChanged));

    public static IList GetSelectedItems(DependencyObject element)
    {
        return (IList)element.GetValue(SelectedItemsProperty);
    }

    public static void SetSelectedItems(DependencyObject element, IList value)
    {
        element.SetValue(SelectedItemsProperty, value);
    }

    private static void OnSelectedItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var selector = (Selector)d;
        var newList = e.NewValue as IList;
        var obs = newList as INotifyCollectionChanged;
        obs.CollectionChanged += OnCollectionChanged;
        selector.SelectionChanged += OnSelectionChanged;
    }

    private static void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        var dependency = (DependencyObject)sender;
        var items = GetSelectedItems(dependency);
        // items.Add/items.Remove
    }

    private static void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        // Update current datagrid selected items .add/.remove
    }

当集合发生变化时,它会将我扔进OnCollectionChanged方法中,但从那里我无法更新我的数据网格。

我已经尝试了几件事,我尝试的第一件事是直接在其中定义事件,OnSelectedItemsChanged因为它obs.CollectionChanged += (s, e2) => {all the code}的访问d导致在数据网格对集合进行更改而无法禁用时触发它。

OnCollectionChanged我尝试的另一种方法是通过向 my 添加一个额外的参数,obs.CollectionChanged += (s, e2) => OnCollectionChanged(s, e2, d);但这也没有让我更进一步,基本上导致了与上述相同的问题。

我尝试/可以找到/可以想出的最后一件事是PropertyChanged在我的事件中使用一个事件OnCollectionChanged并为每个已更改的项目触发它,这是希望能够触发 UI 发送一个我可以挂钩的事件进入并从那里更新(因为它将包含数据网格的依赖对象)。这从来没有奏效,没有任何事件从未触发任何让我陷入死路的事情。

问题如下,当从例如 viewModel 进行更改时,我如何能够设置数据网格(或任何 MultiSelector/Listbox)的选定项目,它不是简单的 1 对 1 绑定,所以它确实需要控制器的一个实例来改变它。

对于那些想知道的人来说,这个想法是它不仅适用于数据网格,还适用于 ListBox 或 MultiSelector 类型的对象,因此我不仅要扩展,而且要创建一个完全独立的dependency property.

标签: c#.netwpfeventsdata-binding

解决方案


您可以使用捕获选择器的本地函数:

private static void OnSelectedItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var selector = (Selector)d;
    var obs = e.NewValue as INotifyCollectionChanged;
    if (obs != null)
    {
        void CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            var dataGrid = selector;
            //...
        }

        obs.CollectionChanged += CollectionChanged;
    }
}

本地函数功能是在 C# 7.0 中引入的。在早期版本中,您可以使用匿名方法:

NotifyCollectionChangedEventHandler handler = (sender, ee) =>
{
    var dataGrid = selector;
    //..
};

obs.CollectionChanged += handler;

推荐阅读