Change brushes based on ViewModel property

£可爱£侵袭症+ 提交于 2019-12-11 10:26:01

问题


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?


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




回答2:


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.



来源:https://stackoverflow.com/questions/33042409/change-brushes-based-on-viewmodel-property

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!