我的应用程序有CarViewModel
+ view
(UserControl
)。
我想要实现的是在绑定的DataContext Car.Status
发生更改时更改画笔的样式。
我发现了如何更改画笔(在视图后面的代码中):
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();
}
}
默认情况下,应用程序和everthing有一个分散在多个文件上的黑暗主题。这个MyBrushes.Light
会覆盖其中一些。
但我不知道如何以MVVM友好的方式基于ViewModel中的属性更改来执行LoadThemeResources函数。
我可以在视图后面的代码中执行:
var vm = (CarViewModel) DataContext;
vm.Car.PropertyChanged += HandleStatusChanged;
但这是View
和ViewModel
之间的紧密耦合。
我也可以通过Messenger(来自MVVM Light)来实现,但是在整个应用程序中广播并且看起来有点过分。
还有其他方法吗?或者首选方式?
答案 0 :(得分:1)
您可以绑定到ViewModel上的属性,并在View中使用IValueConverter将该属性(无论是布尔值,状态枚举等)转换为要使用的Brush。
也就是说,加载转换器中的主题/资源(View和ViewModel之间的故意桥接),以便您的View获得它想要的Brush,并且您的ViewModel只需要公开“重要”信息(有助于决定的位)什么刷加载)。决策逻辑全部在转换器中。
答案 1 :(得分:1)
我会准备一些附加属性(在UserControl
上使用)。将该属性绑定到您的视图模型,并在属性更改的回调中添加LoadThemeResources
的代码逻辑,如下所示:
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) {
//...
}
XAML中的用法 :
<UserControl ...
local:ThemeService.IsPrepareMode="{Binding Car.Status}">
<!-- ... -->
</UserControl>
您还可以为UserControl的类声明一个正常的DependencyProperty
,并使用它而不是附加的属性(用法是相同的)。