Reputation: 331
I have created custom control with generic collection dependency property. But whenever this property is changed from xaml, value in view model in setter is null.
CustomControl:
public IList A
{
get { return (IList)GetValue(AProperty); }
set { SetValue(AProperty, value); }
}
public static readonly DependencyProperty AProperty =
DependencyProperty.Register(nameof(A), typeof(IList), typeof(CustomControl), new PropertyMetadata(new List<object>()));
ViewModel:
List<B> collectionB;
public List<B> CollectionB
{
get { return collectionB; }
set
{
if (collectionB == value) return;
collectionB = value;
}
}
If I change type of CollectionB to List<object> it works fine.
Upvotes: 0
Views: 746
Reputation: 128060
The most generic type of a collection property is IEnumerable
- see for example the ItemsControl.ItemsSource
property.
Also be aware that setting a non-null default value for a collection-type dependency property is problematic, because all instances of the owning class would by default operate on the same collection instance. Adding an element to the A property of one control would change the collection of all other control instances.
You should declare the property like this:
public IEnumerable A
{
get { return (IEnumerable)GetValue(AProperty); }
set { SetValue(AProperty, value); }
}
public static readonly DependencyProperty AProperty =
DependencyProperty.Register(
nameof(A), typeof(IEnumerable), typeof(CustomControl));
In case you really need a non-null default value, add this to the control's constructor:
SetCurrentValue(AProperty, new List<object>());
Update: Using a OneWayToSource
Binding of a collection type property like
<local:CustomControl A="{Binding CollectionB, Mode=OneWayToSource}" />
can only work if the default value of A
is assignment-compatible with the source property of the Binding, which does not hold true for List<object>
and List<B>
.
You should instead not set a default value at all, and instead use a TwoWay Binding
<local:CustomControl A="{Binding CollectionB, Mode=TwoWay}" />
with
private List<B> collectionB = new List<B>();
public List<B> CollectionB
{
get { return collectionB; }
set { collectionB = value; }
}
or just
public List<B> CollectionB { get; set; } = new List<B>();
Upvotes: 1
Reputation: 258
That's because IList<T>
does not implement IList
so casting from one type to the other will fail.
If you want a binding with A
then you must bind it to something that's also implementing IList
Upvotes: 0