在任何布局控件的子项上获取 CollectionChanged 事件?

Get CollectionChanged event on Children's of any Layout control?

如何从任何 LayoutControl 的子级获取 ItemAdded、ItemRemoved 通知?

假设我们有 Grid 控制权。如果我在 Grid 中添加新的 TextBlock 控件,那么它应该通知我添加的项目。如果删除了,它应该通知我已从 Children's (UIElementCollection) 中删除的项目,例如 ObservableCollection.

这可能吗?

不确定您为什么要这样做,但我想您可以扩展网格面板并覆盖 OnVisualChildrenChanged 受保护方法以引发事件:

public class ObservableGrid : Grid
{
    protected override void OnVisualChildrenChanged(DependencyObject visualAdded, DependencyObject visualRemoved)
    {
        base.OnVisualChildrenChanged(visualAdded, visualRemoved);

        if (VisualChildrenChanged != null)
            VisualChildrenChanged(this, new VisualChildrenChangedEventArgs(visualAdded, visualRemoved));
    }

    public event EventHandler<VisualChildrenChangedEventArgs> VisualChildrenChanged;
}

public class VisualChildrenChangedEventArgs : EventArgs
{
    public VisualChildrenChangedEventArgs(DependencyObject visualAdded, DependencyObject visualRemoved)
    {
        VisualAdded = visualAdded;
        VisualRemoved = visualRemoved;
    }

    public DependencyObject VisualAdded { get; private set; }
    public DependencyObject VisualRemoved { get; private set; }
}

如果您能够创建自己的 Panel,您可以覆盖一些虚拟方法以在它的子类中实现 INotifyCollectionChanged。但这需要你自己重新实现布局算法。

public class ObservablePanel : Panel, INotifyCollectionChanged
{
    public event NotifyCollectionChangedEventHandler CollectionChanged = delegate { };

    protected override UIElementCollection CreateUIElementCollection(FrameworkElement logicalParent)
    {
        var oldObservableCollection = InternalChildren as INotifyCollectionChanged;
        if (oldObservableCollection != null)
            oldObservableCollection.CollectionChanged -= OnChildrenChanged;

        var collection = new ObservableUIElementCollection(this, logicalParent);
        collection.CollectionChanged += OnChildrenChanged;

        return collection;
    }

    private void OnChildrenChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        CollectionChanged(sender, e);
    }
}

public class ObservableUIElementCollection : UIElementCollection, INotifyCollectionChanged
{
    public ObservableUIElementCollection(UIElement visualParent, FrameworkElement logicalParent)
        : base(visualParent, logicalParent)
    {
    }

    public event NotifyCollectionChangedEventHandler CollectionChanged = delegate { };

    public override int Add(UIElement element)
    {
        var i = base.Add(element);

        IList newItems = new List<UIElement> { element };
        IList oldItems = new List<UIElement>();
        CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, newItems, oldItems));

        return i;
    }

    ...
}

如果您知道,您只使用 Grid,则可以将其子类化。但是我没有看到一种方法可以同时将 INotifyCollectionChanged 添加到 PresentationFramework 中现有的所有面板。

由于您正在尝试构建自己的 Collection 控件,IMO 您应该从 Microsoft 的 ItemsControl 实现中获得灵感。 您应该检查的方法是:

private void CreateItemCollectionAndGenerator()

private void OnItemCollectionChanged1(object sender, NotifyCollectionChangedEventArgs e)

internal void AdjustItemInfos(NotifyCollectionChangedEventArgs e, IEnumerable list)

总的来说,这个 class 是一项很好的研究,可以帮助您了解在以最通用的可能方式实现您自己的 ItemsCollection 时的思维过程。