EDIT:
In order to clear up all confusions with instanct-closing as duplicates. Please see point (3.) explaining why the accepted answer does not apply. In short, the linked answer is fine as long as you are not using XAML to set the value because XAML will never call PropertyChangedCallback
because it re-uses the default instance.
Question:
Considering a simple WPF's Attached Property of ObservableCollection<T>
type with XAML-defined value:
// public static class MyCollectionExetension.cs
public static ObservableCollection<int> GetMyCollection(DependencyObject obj)
{
return (ObservableCollection<int>)obj.GetValue(MyCollectionProperty);
}
public static void SetMyCollection(DependencyObject obj, ObservableCollection<int> value)
{
obj.SetValue(MyCollectionProperty, value);
}
public static readonly DependencyProperty MyCollectionProperty =
DependencyProperty.RegisterAttached("MyCollection", typeof(ObservableCollection<int>),
typeof(MyCollectionExetension), new PropertyMetadata(null);
public static void DoThisWhenMyCollectionChanged(DependencyObejct assignee, IEnumerable<int> newValues) {
// how can I invoke this?
}
//UserControl.xaml
<Grid xmlns:sys="clr-namespace:System;assembly=mscorlib">
<b:DataGridExtensions.MyCollection >
<sys:Int32>1</sys:Int32>
<sys:Int32>2</sys:Int32>
</b:DataGridExtensions.MyCollection>
</Grid>
How can I hook collection changed events with access to the both the DependencyObject
it is attached to and the new items? MyCollection must be definable in XAML.
It seems simple at first, but none of following worked for me:
- Set callback
new UIPropertyMetadata(null, CollectionChanged)
causes crash:
XamlObjectWriterException: 'Collection property 'System.Windows.Controls.Grid'.'MyCollection' is null.'
OK, let's provide default value in order to avoid the crash above:
new UIPropertyMetadata(new ObservableCollection<int>(), CollectionChanged)
That, however preventCollectionChanged
from ever firing due to XAML not instantiating new collection but rather adding items to existing collection.Fixing the above and hook
CollectionChanged
while providing default valuenew UIPropertyMetadata(ProvideWithRegisteredCollectionChanged(), CollectionChanged)
does not work neither because there is no way to pass theDependencyProperty
toProvideWithRegisteredCollectionChanged()
method due to being in static context.- Coalescing in
MyCollection
either inGetMyCollection()
getter orCoerceValueCallback
does not prevent the crash from point 1. above since it does not seem to be called before property is first accessed.