C# 在任何布局控件的子控件上获取CollectionChanged事件?
如何从任何LayoutControl的子级获取ItemAdded、ItemRemoved通知 假设我们有网格控制。若我在网格中添加了新的TextBlock控件,那个么它应该会用添加的项通知我。如果已删除,则它应通知我已从该子级UIElementCollection中删除的项,如ObservableCollectionC# 在任何布局控件的子控件上获取CollectionChanged事件?,c#,wpf,layout,children,C#,Wpf,Layout,Children,如何从任何LayoutControl的子级获取ItemAdded、ItemRemoved通知 假设我们有网格控制。若我在网格中添加了新的TextBlock控件,那个么它应该会用添加的项通知我。如果已删除,则它应通知我已从该子级UIElementCollection中删除的项,如ObservableCollection 这可能吗?不确定为什么要这样做,但我想您可以扩展网格面板并覆盖OnVisualChildrenChanged保护方法以引发事件: public class ObservableGr
这可能吗?不确定为什么要这样做,但我想您可以扩展网格面板并覆盖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模式将获得更好的可测试性。请看一个不相关的问题作为例子。