【问题标题】:Loading a ResourceDictionary via binding from App.xaml?通过从 App.xaml 绑定加载 ResourceDictionary?
【发布时间】:2014-07-01 12:16:40
【问题描述】:

我有一个 WPF 应用程序,我们需要根据配置文件设置重新设置该应用程序。 App.xaml 的简单版本是:

App.xaml

<Application>
  ...
  <Application.Resources>
    <ResourceDictionary x:Key="NormalMain">
        <ImageBrush x:Key="BackgroundBrush" ImageSource="Images/welcome.png"/>
    </ResourceDictionary>
    <ResourceDictionary x:Key="AlternateMain">
        <SolidColorBrush x:Key="BackgroundBrush" Color="LightGreen"/>
    </ResourceDictionary>
  </Application.Resources>
  ...
</Application>

我想根据配置文件设置在运行时加载资源字典。我已经绑定了绑定并且知道它可以工作,但是我无法确定合并这个特定字典的方法。

MainWindowView.xaml

<Window 
    (...)
    d:DataContext="{d:DesignInstance designer:DesignMainWindowViewModel, IsDesignTimeCreatable=True}"
    Background="{StaticResource BackgroundBrush}">
    ...
    <Window.Resources>
      //Load dictionary based on binding here?
    </Window.Resources>
</Window>

MainWindowViewModel 很简单,例如:

MainWindowViewModel.cs

public class MainWindowViewModel {
  public bool IsAlternate {get;set;}
}

有没有办法正确地做到这一点?

编辑:我不想在代码隐藏中进行加载,并且 PACK 语法在这种情况下似乎与引擎的构建方式不同。

编辑 2:我在 App.xaml 中使用此代码有点接近:

    <StaticResource ResourceKey="{Binding Path=IsAlternate, Converter={StaticResource BoolToResourceKeyId}}" />

但是当我看到它时,它会导致我认为出现一堆奇怪的错误。

【问题讨论】:

    标签: c# wpf xaml mvvm resourcedictionary


    【解决方案1】:

    经过几个小时的战斗,我找到了一种不同的处理方式。

    我为我在 app.xaml 中工作的控件创建了两种样式:

    App.xaml

       ...
        <valueConverters:IsMainToStyleConverter x:Key="IsMainToStyleConverter" />
        <Style x:Key="Main" TargetType="Window">
            <Setter Property="Background" Value="{StaticResource MainBackgroundBrush}" />
        </Style>
        <Style x:Key="Alternate" TargetType="Window">
            <Setter Property="Background" Value="{StaticResource AlternateBackgroundBrush}" />
        </Style>
       ...
    

    然后定义了一个可以用来定位样式的转换器:

    IsMainToStyleConverter.cs

    public class IsMainToStyleConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return Application.Current.TryFindResource((value is bool && ((bool)value) ? "Main" : "Alternate"));
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return Binding.DoNothing;
        }
    }
    

    并修复了我的 MainWindowView:

    MainWindowView.xaml

    <Window 
       ...
       d:DataContext="{d:DesignInstance designer:DesignMainWindowViewModel, IsDesignTimeCreatable=True}"
       Style="{Binding IsMain, Converter={StaticResource IsMainConverter}}">
       ...
    </Window>
    

    现在,只要我的视图模型具有正确的属性,转换器就会处理定位样式资源并切换到它,而不必担心超越模式问题或类似的事情。

    【讨论】:

      【解决方案2】:

      我认为 XAML 中没有基于您的绑定的语法来执行此操作。

      但是您可以做的是在您的 viewModel 的 PropertyChanged 事件上创建一个事件处理程序,并在此处理程序中检查“IsAlternate”的值,然后使用:

      Application.Current.Resources.MergedDictionaries.Add
      

      并打包 URI,以添加/删除正确的资源字典

      【讨论】:

      • 在我工作的地方,我们使用的是 MVVM,我们没有在视图中使用代码隐藏,并且 ViewModel 无法了解视图来执行此操作。
      • 我的答案基于您的“IsAlternate”属性,您可以在视图中绑定。它不会破坏 MVVM 模式
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-19
      • 2011-01-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多