2

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?

2 Answers 2

1

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).

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks it works! Is it really neceserry to use a seperate class instead of doing it directly in the UserControl code? I'm getting some errors trying to do so: stackoverflow.com/questions/33076560/…
@RvdK I believe you can do so, but in your code from that question, you actually make it understand Status as an attached property, but it's of course not, try replacing views:CarView.Status with just Status.
If I do that, it will give errors. The property 'Status' was not found in type 'UserControl'"
@RvdK yes, that's correct. It looks for that property on UserControl, you can try also changing the tag, instead of UserControl, use your custom user control name, don't forget to use prefix namespace defined inside your UserControl, e.g: <local:CustomUserControl .... xmlns:local="...">...
1

You could bind to a property on your ViewModel, and use an IValueConverter in your View to turn that property (whether boolean, status enumeration, whatever) into a Brush to be used.

That is, load the theme/resources in the converter (a deliberate bridge between View and ViewModel) so that your View gets the Brush it wants and your ViewModel only has to expose the 'important' information (the bits that help decide what brush to load). The decision logic is all in the converter.

4 Comments

You mean a pure XAML solution? Do you have any example code how that would look?
I think I've misunderstood you slightly - what are you trying to do? Why are you loading a whole themedictionary based on a single Boolean value?
I'm trying to style a UserControl (and inner UserControls). Lot's of brushes will need to be replaced. These brushes are used troughout the Car UserControl and childs.
A converter is preferable to modifying a resource, if you base the converter on an enumeration of values, then you can ensure colour options for all Staus values.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.