Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/294.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在任何布局控件的子控件上获取CollectionChanged事件?_C#_Wpf_Layout_Children - Fatal编程技术网

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

C# 在任何布局控件的子控件上获取CollectionChanged事件?,c#,wpf,layout,children,C#,Wpf,Layout,Children,如何从任何LayoutControl的子级获取ItemAdded、ItemRemoved通知 假设我们有网格控制。若我在网格中添加了新的TextBlock控件,那个么它应该会用添加的项通知我。如果已删除,则它应通知我已从该子级UIElementCollection中删除的项,如ObservableCollection 这可能吗?不确定为什么要这样做,但我想您可以扩展网格面板并覆盖OnVisualChildrenChanged保护方法以引发事件: public class ObservableGr

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

假设我们有网格控制。若我在网格中添加了新的TextBlock控件,那个么它应该会用添加的项通知我。如果已删除,则它应通知我已从该子级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; }
}

不确定为什么要这样做,但我想您可以扩展网格面板并覆盖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; }
}

如果您能够创建自己的面板,则可以重写一些虚拟方法,以在其子类中实现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;
    }

    ...
}

若您知道,您只使用网格,那个么您可以将其子类化。但是我看不到一种方法可以将INotifyCollectionChanged添加到PresentationFramework中现有的所有面板。

如果您能够创建自己的面板,则可以覆盖一些虚拟方法,以在其子类中实现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;
    }

    ...
}

若您知道,您只使用网格,那个么您可以将其子类化。但是我没有看到一种方法可以将InotifyCollection同时添加到PresentationFramework中现有的所有面板。

既然您正在尝试构建自己的集合控件,我认为您应该从Microsoft的ItemsControl实现中获得灵感。 您应该检查的方法有:


一般来说,本课程是一个很好的学习,可以了解以最通用的方式实现自己的ItemsCollection时的思考过程。

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


一般来说,本课程是一个很好的学习,目的是了解以最通用的方式实现自己的ItemsCollection时的思维过程。

@kyle我正试图通过覆盖UIElementCollection&Setting[ContentPropertyChildren]来创建自己的孩子的集合overidden LayoutControl上的MarkupExtension…尝试使用名为例如UIElementObservableCollection的属性创建您自己的GridControl。我已经通过创建自己的名为ObservableCurrentQueue的并发队列实现了这一点,它应该是类似的?使用listbox@kyle我正试图通过在overidden LayoutControl上重写UIElementCollection并设置[ContentPropertyChildren]MarkupExtension来创建自己的子集合…尝试使用名为例如UIElementObservableCollection的属性创建自己的GridControl。我已经通过创建自己的名为ObservableCurrentQueue的并发队列实现了这一点,它应该是类似的?使用ListBoxes完全一样,我正试图做。但我忘了重写CreateUIElementCollection方法。。非常感谢Wigy。我很高兴这个解决方案对您有所帮助。如果您有足够的时间进行重构,那么使用MVVM模式将获得更好的可测试性。以一个不相关的问题为例。完全相同的事情,我试图做。但我忘了重写CreateUIElementCollection方法。。非常感谢Wigy。我很高兴这个解决方案对您有所帮助。如果您有足够的时间进行重构,那么使用MVVM模式将获得更好的可测试性。请看一个不相关的问题作为例子。