我有自定义控件MyGrid
public class MyGrid : Canvas
{
//...
ObservableCollection<object> items = new ObservableCollection<object>();
public ObservableCollection<object> Items
{
get { return items; }
set {
items = value;
UpdateValues();
UpdateGrid();
}
}
//..
}
我希望Items可从XAML代码绑定:
<local:MyGrid Items="{Binding Numbers}" />
其中Numbers是ObservableCollection(效果很好,我可以使用它绑定到默认控件)。我试图将Items定义为DependencyProperty,但是它是静态的,我需要在页面上使用多个控件来处理不同的数据源,因此使用静态项将不起作用。上面的代码无法正常运行。InitializeComponent()引发异常:无法分配给属性“ App.MyGrid.Items”。[线:27位:114]。我该如何运作?
随着MyGrid从Canvas扩展(最后也是DependecyObject),您可以在MyGrid内实现Dependency属性。
然后,您还可以使用来实现它,PropertyChangedCallback
从而允许您注册/注销事件本身,然后可以在其中更新表格/值
因此,您可以像这样更改MyGrid:
public class MyGrid : Canvas
{
protected static PropertyChangedCallback ItemsPropertyChangedCallback = new PropertyChangedCallback(ItemsPropertyChanged);
public static DependencyProperty ItemsProperty = DependencyProperty.RegisterAttached("Items", typeof(INotifyCollectionChanged), typeof(MyGrid), new PropertyMetadata(null, ItemsPropertyChangedCallback));
private static void ItemsPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
MyGrid thisGrid = (MyGrid)sender;
if (thisGrid == null)
{
return;
}
thisGrid.UnregisterItems(e.OldValue as INotifyCollectionChanged);
thisGrid.RegisterItems(e.NewValue as INotifyCollectionChanged);
thisGrid.Refresh();
}
public INotifyCollectionChanged Items
{
get
{
return (INotifyCollectionChanged)GetValue(ItemsProperty);
}
set
{
SetValue(ItemsProperty, value);
}
}
protected void UnregisterItems(INotifyCollectionChanged items)
{
if (items == null)
{
return;
}
items.CollectionChanged -= ItemsChanged;
}
protected void RegisterItems(INotifyCollectionChanged items)
{
if (items == null)
{
return;
}
items.CollectionChanged += ItemsChanged;
}
protected virtual void UpdateValues()
{
System.Diagnostics.Debug.WriteLine("Updating values");
}
protected virtual void UpdateGrid()
{
System.Diagnostics.Debug.WriteLine("Updating grid");
}
public void Refresh()
{
UpdateValues();
UpdateGrid();
}
protected virtual void ItemsChanged(object sender, NotifyCollectionChangedEventArgs e)
{
Refresh();
}
public MyGrid()
{
}
}
然后在Xaml中可以稍后绑定到Items属性。当Items属性被另一个集合更改时,它将从最后一个对象(如果有)的更改事件中注销,然后注册到新对象(如果有一个)。之后,它将调用您的类的Refresh方法(然后调用UpdateValues / UpdateGrid方法)
我也部分同意@ user3248647的观点,即您应尽可能利用Binding和ContentTemplates,但如果不能使用Binding和ContentTemplates,则至少可以像这样使DependencyProperty做出反应。
是的,DependencyProperty在类上是静态的,但是属性本身始终在类内部实现。使用PropertyChangedCallback时,只需将发送方强制转换回“ MyGrid”,然后就可以更改实例成员了:)
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句