Reputation: 134
I am trying to create a CustomUserControl in WPF. This CustomUserControl contains a DependencyProperty of type ObservableCollection.
My goal is to be able to:
Here is what I have right now:
<my:CustomUserControl ImageList={Binding imgList}/>
ImageList is defined as the following:
public static readonly DependancyProperty ImageListProperty = DependancyProperty.Register
("ImageList", typeof(List<ImageSource>), typeof(Switch));
public List<ImageSource> ImageList {
get { return (List<ImageSource>)GetValue(ImageListProperty); }
set { SetValue(ImageListProperty, value); }
}
In order to have a new instance of ImageList per CustomUserControl, I have added the following line in the ctor of CustomUserControl:
public CustomUserControl(){
...
SetValue(ImageListProperty, new List<ImageSource>());
}
Now, the following code examples work:
<my:CustomUserControl>
<my:CustomUserControl.ImageList>
<BitmapImage UriSource="Bla.png"/>
<BitmapImage UriSource="Bla2.png"/>
</my:CustomUserControl.ImageList>
</my:switch>
And this works too:
<my:CustomUserControl ImageList={Binding imgList}/>
But this does not:
<Style TargetType="my:CustomUserControl">
<Setter Property="my:CustomUserControl.ImageList">
<BitmapImage UriSource="Bla.png"/>
<BitmapImage UriSource="Bla2.png"/>
</Setter>
</Style>
This leaves all instances with an empty ImageList.
P.S. This is pseudo-code as I don't recall the exact syntax.
Thanks!
Upvotes: 3
Views: 113
Reputation: 30498
The reason why you aren't able to set the value in a Style
is because you are setting a local value in your constructor. MSDN explains DependencyProperty
value precedence in more detail.
Because you just want to give your property a default value per instance, just use SetCurrentValue
instead of SetValue
in your constructor.
Edit to explain this further
So, a DependencyProperty
can be set in multiple ways. It can be set through code, a Binding
, a Style
, a Trigger
, an Animation
, or a few other ways. The important thing to know is that there can be multiple attempts to set a given property.
Because of this, WPF has defined a precedence for the values. That means if you set a property in a Style
, you can set the property manually to override the Style
value. Or a Trigger
in the ControlTemplate
can override the Style
value.
When you set the property in your constructor, you are giving it a local value. From the first link, you will see that only an Animation
or Property Coercion
can override a local value.
The SetCurrentValue
method, however, will allow you to set a value for a property without setting a local value. This is what you need, as you want to be able to set the value in a Style
.
Upvotes: 1
Reputation: 19296
Instead of using List<ImageSource>
you should use CompositeCollection
(msdn)
public CompositeCollection ImageList
{
get { return (CompositeCollection)GetValue(ImageListProperty); }
set { SetValue(ImageListProperty, value); }
}
public static readonly DependencyProperty ImageListProperty =
DependencyProperty.Register("ImageList", typeof(CompositeCollection), typeof(CustomUserControl), new PropertyMetadata(new CompositeCollection()));
And now you can set values in the defined style like this:
<my:CustomUserControl x:Name="myCustomUserControl
<my:CustomUserControl.Style>
<Style TargetType="{x:Type my:CustomUserControl}">
<Setter Property="my:CustomUserControl.ImageList">
<Setter.Value>
<CompositeCollection>
<BitmapImage UriSource="Bla.png"/>
<BitmapImage UriSource="Bla2.png"/>
</CompositeCollection>
</Setter.Value>
</Setter>
</Style>
</my:CustomUserControl.Style>
</my:CustomUserControl>
Other binding works in the same way as you presented in your question.
e.g.:
<my:CustomUserControl x:Name="myCustomUserControl">
<my:CustomUserControl.ImageList>
<BitmapImage UriSource="Bla.png" />
<BitmapImage UriSource="Bla2.png" />
</my:CustomUserControl.ImageList>
</my:CustomUserControl>
Upvotes: 0