For a Silverlight and WPF app, I have a custom control that includes an ObservableCollection
as a dependency property. One element of that control, a Border, needs to change color depending on the composition of items in the ObservableCollection
.
For example, let's say the collection is of animals, vegetables, and minerals and called ObjectList
. If there is at least one animal, I want the border to be red; if there are no animals but at least one vegetable, it's green; otherwise the collection has only minerals, so will appear as blue.
I created a converter that can take the collection and determine the color, so have a binding like:
<Border Background="{Binding ObjectList,
RelativeSource={RelativeSource Self},
Converter={StaticResource MyColorConverter}}" />
The challenge is that as items get added/removed from ObjectList
I need to trigger reevaluation of the background color; however, ObjectList
itself doesn't change. I figure I have three options, but am unsure of which may be the best practice:
Create a new collection each time an object is added or removed. That seems heavy-handed, but will result in
ObjectList
being changed and so trigger the background update.Call
UpdateTarget
for the background property in theCollectionChanged
callback forObjectList
. SinceUpdateTarget
isn't available for Silverlight, I just remove and re-add the binding - again a bit heavy handed.Implement
INotifyPropertyChanged
on my custom control and callPropertyChanged
on theObjectList
within the implementation ofCollectionChanged
I like 3 the best, but the fact I have a DependencyObject that also implements INPC seems odd. Is it? Is there a more elegant approach?
There is a way of doing this recommended by the MSDN documentation (scroll down to Best Practices for Working with the VisualStateManager; it's written for full .Net but this section is well suitable for Silverlight too). Whenever your
VisualStates
depend on properties/state of your customControl
it is recommended to have a ChangedHandler for each VisualState-affecting property and call a privateUpdateVisualStates
method from there. Evaluate your conditions and set theVisualStates
programmatically from within this method.Even if you are not using
VisualStates
for the color change I recommend you follow this same pattern.The following code is left incomplete for brevity:
Feel free to introduce a DependencyProperty BorderColor and bind to it from your xaml if you don't want to have a reference to the border. It's fine. And there is really no problem with having another moving part. That's way better than simulating that the whole ObjectList instance changed.