WPF - 在UserControl中绑定ObservableCollection依赖项属性

Joh*_*ohn 7 c# data-binding wpf dependency-properties observablecollection

我控制了一下

class DragGrid:Grid {...}

它继承自原始网格,并允许拖动和调整其子元素的大小.我需要将一个自定义DP绑定WorkItemsProperty到一个可观察的类型集合WorkItem(implements INotifyPropertyChanged).网格中的每个元素都绑定到一个集合项.

每当用户在运行时动态添加新项目(无法在XAML中声明项目!),或从该集合中删除项目时,WorkItems应更新DragGrid上的DP,以及网格中的子项(每个子项代表一个项目)WorkItem收集项目).

我的问题是DP如何通知控件必须删除网格中的哪个子元素,更改('更改'表示用户拖动元素,或用鼠标调整大小)或添加,以及如何识别哪一个现有的子项是需要删除或更改的子项.我知道这是DependencyPropertyChangedCallback的用武之地.但是只有在重新设置DP属性时才会调用它,而不是在集合中的某些内容发生更改时(如add,remove item).那么最后,DragGrid控件是否需要订阅CollectionChanged事件?在什么时候我会为此事件处理程序挂钩?

*编辑:: 首先使用网格的原因是因为我希望能够在用户拖动或调整网格中的控件时保持最小增量.控件表示时间跨度,每个网格列表示15分钟(这是最小值).使用Thumbs在Canvas中执行此操作非常困难且错误.实现DragGrid解决了我的用户交互问题.此外,Canvas不可扩展,因此时间跨度必须不断重新计算.使用网格,我没有问题,因为列无论大小都告诉我时间.**

Jos*_*h G 17

回答你的实际问题:

您应该添加DepencyPropertyChanged处理程序,如您所述.在此处理程序中,您应该将事件处理程序添加到新集合上的CollectionChanged属性,并从旧集合中删除处理程序,如下所示:

    public ObservableCollection<WorkItem> WorkItems
    {
        get { return (ObservableCollection<WorkItem>)GetValue(WorkItemsProperty); }
        set { SetValue(WorkItemsProperty, value); }
    }

    // Using a DependencyProperty as the backing store for WorkItems.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty WorkItemsProperty =
        DependencyProperty.Register("WorkItems", typeof(ObservableCollection<WorkItem>), typeof(DragGrid), new FrameworkPropertyMetadata(null, OnWorkItemsChanged));

    private static void OnWorkItemsChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        DragGrid me = sender as DragGrid;

        var old = e.OldValue as ObservableCollection<WorkItem>;

        if (old != null)
            old.CollectionChanged -= me.OnWorkCollectionChanged;

        var n = e.NewValue as ObservableCollection<WorkItem>;

        if (n != null)
            n.CollectionChanged += me.OnWorkCollectionChanged;
    }

    private void OnWorkCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        if (e.Action == NotifyCollectionChangedAction.Reset)
        {
            // Clear and update entire collection
        }

        if (e.NewItems != null)
        {
            foreach (WorkItem item in e.NewItems)
            {
                // Subscribe for changes on item
                item.PropertyChanged += OnWorkItemChanged;

                // Add item to internal collection
            }
        }

        if (e.OldItems != null)
        {
            foreach (WorkItem item in e.OldItems)
            {
                // Unsubscribe for changes on item
                item.PropertyChanged -= OnWorkItemChanged;

                // Remove item from internal collection
            }
        }
    }

    private void OnWorkItemChanged(object sender, PropertyChangedEventArgs e)
    {
        // Modify existing item in internal collection
    }
Run Code Online (Sandbox Code Playgroud)

作为gehho解释说,像你没有使用网格类的原本打算,虽然你可能是太远的发展,希望在这一点上,开始了声音.从Panel派生的类实际上只是为了在视觉上绘制/安排他们的孩子,而不是操纵和增强他们.查看ItemsControlWPF内容模型以了解更多信息.