我有一个自定义控件,我有一个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];
}
}
这个Dependency属性绑定到Viewmodel中的一个可观察集合,我的问题是如果我在Viewmodel的构造函数中添加一些视图模型observable集合OnChangeSelectedItems被调用,但是如果我在运行时在observable集合中添加更多项目,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
}
答案 0 :(得分:3)
您将对象(列表本身)的更改与内容更改(项目)混淆。只有在更改列表对象时才会调用OnChangeSelectedItems
。
在更改方法中,您可以测试集合是否实现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
词典的关键。