I have an application which has CarViewModel
+ view
(UserControl
).
What I want to achieve is to change the style of brushes when the bound DataContext Car.Status
changes.
I found out how to change the brushes (in code behind of the view):
private void LoadThemeResources(bool isPrepareMode)
{
if (isPrepareMode)
{
Uri themeUri = new Uri(@"/../Resources/MyBrushes.Light.xaml", UriKind.Relative);
ResourceDictionary themeDictionary = Application.LoadComponent(themeUri) as ResourceDictionary;
this.Resources.MergedDictionaries.Add(themeDictionary);
}
else
{
this.Resources.MergedDictionaries.Clear();
}
}
By default the application and everthing has a dark theme spread over multiple files. This MyBrushes.Light
overwrites some of those.
But I have no clue how I can execute the LoadThemeResources function based on a property change in the ViewModel in a MVVM friendly way.
I can do in the code behind of the view:
var vm = (CarViewModel) DataContext;
vm.Car.PropertyChanged += HandleStatusChanged;
But this is a tight coupling between View
and ViewModel
.
I can also do it via Messenger (From MVVM Light), but that gets broadcasted throughout the whole application and seems overkill.
Is there an other way? Or preferred way?
I would prepare some attached property (used on UserControl
). Bind that property to your view-model and add code logic of LoadThemeResources
in the property changed callback, something like this:
public static class ThemeService {
public static DependencyProperty IsPrepareModeProperty =
DependencyProperty.RegisterAttached("IsPrepareMode", typeof(bool), typeof(ThemeService),
new PropertyMetadata(isPrepareModeChanged));
public static bool GetIsPrepareMode(UserControl e){
return (bool) e.GetValue(IsPrepareModeProperty);
}
public static void SetIsPrepareMode(UserControl e, bool value){
e.SetValue(IsPrepareModeProperty, value);
}
static void isPrepareModeChanged(object sender, DependencyPropertyChangedEventArgs e){
var u = sender as UserControl;
u.LoadThemeResources((bool)e.NewValue);
}
}
//you need some public method of LoadThemeResources
public void LoadThemeResources(bool isPrepareMode) {
//...
}
Usage in XAML:
<UserControl ...
local:ThemeService.IsPrepareMode="{Binding Car.Status}">
<!-- ... -->
</UserControl>
You can also declare a normal DependencyProperty
for your UserControl's class and use that instead of the attached property (the usage is just the same).