改变方法不叫上IList的依赖属性
问题描述:
我有,我有一个IList的依赖属性改变方法不叫上IList的依赖属性
public IList SelectedItems
{
get { return (IList)GetValue(SelectedItemsProperty); }
set { SetValue(SelectedItemsProperty, value); }
}
public static readonly DependencyProperty SelectedItemsProperty =
DependencyProperty.Register("SelectedItems", typeof(IList),
typeof(MyCustomControl), new FrameworkPropertyMetadata(OnChangeSelectedItems)
{
BindsTwoWayByDefault = true
});
private static void OnChangeSelectedItems(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var usercontrol = d as MyCustomControl;
var selected = e.NewValue as IList;
if (selected != null && selected.Count > 1)
{
//do something
usercontrol.label1.Content= selected[0];
}
}
这种依赖属性绑定到视图模型可观察集合的自定义控件,我的问题是,如果我加入一些在ViewModel OnChangeSelectedItems的构造函数中的视图模型可观察集合被调用,但如果我在可观察集合中的运行时添加更多项目,OnChangeSelectedItems不会被调用。我在这里丢失了什么。
编辑:工作液
private static void OnChangeSelectedItems(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var uc = d as UserControl1;
if (uc != null)
{
var oldObservable = e.OldValue as INotifyCollectionChanged;
var newObservable = e.NewValue as INotifyCollectionChanged;
if (oldObservable != null)
{
oldObservable.CollectionChanged -= uc.SelectedItemsContentChanged;
}
if (newObservable != null)
{
newObservable.CollectionChanged += uc.SelectedItemsContentChanged;
}
}
}
private void SelectedItemsContentChanged(object d, NotifyCollectionChangedEventArgs e)
{
//do something
}
答
你混淆了对象与内容(项目)的变化的变化(列表本身)。 OnChangeSelectedItems
只会在列表对象改变时被调用。
在change方法中,您可以测试集合是否实现INotifyCollectionChanged
并手动处理后续更改。
编辑
您希望在执行上的项目更新的一些操作来访问上下文用户控件。这意味着您需要为CollectionChanged事件创建专门的处理程序实例。此外,您需要跟踪处理程序,以便稍后在出于某种原因将列表换出时将其删除。以下代码示例中的CurrentHandlers
完成此操作。 代码以注册为收集相关的改变可能看起来像这样:
private static Dictionary<INotifyCollectionChanged, NotifyCollectionChangedEventHandler> CurrentHandlers = new Dictionary<INotifyCollectionChanged, NotifyCollectionChangedEventHandler>();
private static void OnChangeSelectedItems(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var usercontrol = d as MyCustomControl;
var selected = e.NewValue as IList;
var oldObservable = e.OldValue as INotifyCollectionChanged;
var newObservable = e.NewValue as INotifyCollectionChanged;
NotifyCollectionChangedEventHandler handler;
if (oldObservable != null && CurrentHandlers.TryGetValue(oldObservable, out handler))
{
oldObservable.CollectionChanged -= handler;
CurrentHandlers.Remove(oldObservable);
}
if (newObservable != null)
{
handler = new NotifyCollectionChangedEventHandler((sender, e2) => SelectedItemsContentChanged(sender, e2, usercontrol));
newObservable.CollectionChanged += handler;
CurrentHandlers.Add(newObservable, handler);
}
if (selected != null && selected.Count > 1)
{
//do something
}
}
private static void SelectedItemsContentChanged(object sender, NotifyCollectionChangedEventArgs e, MyCustomControl usercontrol)
{
//do something
}
注意,这(在前面的例子不同)是不是真的健壮。如果多次绑定相同的列表,CurrentHandlers
存储将无法按预期工作。所以一定要选择一个处理程序存储机制,它可以安全地处理您的属性的使用案例。
一个想法,可能工作:var keyTuple = Tuple.Create(usercontrol, oldObservable);
(或newObservable
)作为CurrentHandlers
字典的关键。
@Clemens虽然它肯定是重复的,但我认为这个链接的Q/A没有一个好的标题以便作为参考。 – grek40