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
ObjectListbeing changed and so trigger the background update.Call
UpdateTargetfor the background property in theCollectionChangedcallback forObjectList. SinceUpdateTargetisn't available for Silverlight, I just remove and re-add the binding - again a bit heavy handed.Implement
INotifyPropertyChangedon my custom control and callPropertyChangedon theObjectListwithin 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
VisualStatesdepend on properties/state of your customControlit is recommended to have a ChangedHandler for each VisualState-affecting property and call a privateUpdateVisualStatesmethod from there. Evaluate your conditions and set theVisualStatesprogrammatically from within this method.Even if you are not using
VisualStatesfor 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.