【问题标题】:Let the user change the resource dictionnary让用户更改资源字典
【发布时间】:2014-07-03 12:02:37
【问题描述】:

我所有的样式和模板都位于名为“design.xaml”的资源字典中,因此在我拥有的每个用户控件中:

<UserControl.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="/MyProject;component/design.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </UserControl.Resources>

但我想让用户通过创建 2 个内部具有相同模板的资源字典来选择他喜欢的设计(每个模板具有不同颜色的相同键)。

例如文件 design.xaml 和 design2.xaml

我该怎么做?是否可以使用代码动态更改资源字典?

谢谢!

【问题讨论】:

  • 我所有的样式和模板都位于一个名为“design.xaml”的资源字典中,所以在每个用户控件中我[导入它]...听说过Application.Resources ?您可以只在其中导入一次ResourceDictionary。

标签: c# wpf xaml resources resourcedictionary


【解决方案1】:

ResourceDictionary1

<Style x:Key="StyleTitleText" TargetType="TextBlock">
    <Setter Property="FontFamily" Value="Arial" />
    <Setter Property="FontSize" Value="14"/>
    <Setter Property="Foreground" Value="Green" />
</Style>

ResourceDictionary2

<Style x:Key="StyleTitleText" TargetType="TextBlock">
  <Setter Property="FontFamily" Value="Arial" />
  <Setter Property="FontSize" Value="14"/>
  <Setter Property="Foreground" Value="Red" />
</Style>

MainWindow xaml

如果主题需要动态更新 UI(即无需重新加载整个 UI),您需要使用 DynamicResource 而不是 StaticResource。

<Window.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="design.xaml" />
            <ResourceDictionary Source="design2.xaml" />
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Window.Resources>

<StackPanel Orientation="Horizontal">
    <ToggleButton Name="Radiobtn" Content="Switch ResourceDictionary" Height="35"   FontSize="12" Margin="0,0,50,0"  Click="RadioButton_Checked_1"></ToggleButton>
    <TextBlock Style="{DynamicResource StyleTitleText}" Text="hfghfhgfhgfhgfghfhfhgf" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center"></TextBlock>
</StackPanel>

c#

  ResourceDictionary r1;
  ResourceDictionary r0;
    public MainWindow()
    {
        InitializeComponent();
        r1 = this.Resources.MergedDictionaries[1];
        r0 = this.Resources.MergedDictionaries[0];
        this.Resources.MergedDictionaries.Remove(r1);

    }

    private void RadioButton_Checked_1(object sender, RoutedEventArgs e)
    {
        this.Resources.Clear();
        if (Radiobtn.IsChecked == true)
        {
            this.Resources.MergedDictionaries.Add(r0);
        }
        else
        {
            this.Resources.MergedDictionaries.Add(r1);
        }
    }

【讨论】:

  • 如果我有很多 UserControl 并且在每个 UC 中我必须调用我的函数,这将删除一个字典?
【解决方案2】:

您可以使用以下代码在后面的代码中轻松加载ResourceDictionary:

ResourceDictionary resourceDictionary = new ResourceDictionary { Source = 
    new Uri("/AssemblyName;component/OptionalFolderName/ResourceDictionaryName.xaml", 
    UriKind.RelativeOrAbsolute) };
YourCurrentUserControlOrWindow.Resources.MergedDictionaries.Add(resourceDictionary);

【讨论】:

    【解决方案3】:

    假设您有一个组合框下拉菜单可以让用户选择样式,您可以执行以下操作

    具有通过名为 StyleDefinition 的数据模型定义的样式集合的 ViewModel

    // Showing the viewmodel constructor only
    public ViewModel()
    {
        this.AvailableStyles = new ObservableCollection<StyleDefinition>()
        {
            new StyleDefinition() { Name="Red", ResourceUri="Design.xaml" },
            new StyleDefinition() { Name="Green", ResourceUri="Design2.xaml" }
        };
    }
    
    // Definition of a simple data model to store style name and uri
    public class StyleDefinition
        {
            public string Name { get; set; }
            public string ResourceUri { get; set; }
        }
    

    现在将集合绑定到组合框,并在 selectionchanged 上设置一个简单的事件处理程序

    <ComboBox Height="50" x:Name="StyleChanger" ItemsSource="{Binding Path=AvailableStyles}" 
                  SelectedValuePath="ResourceUri" DisplayMemberPath="Name" 
                  SelectionChanged="StyleChanger_SelectionChanged">
    

    选择更改后面的代码:

    private void StyleChanger_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        var style = this.StyleChanger.SelectedItem as StyleDefinition;
        this.Resources.MergedDictionaries[0].Source = new Uri(style.ResourceUri, UriKind.Relative);
    }
    

    底线是您只需将 MergedDictionaries[0] 的 Source 属性更改为用户选择的属性。这将动态改变样式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多