在WPF中运行时更改样式

18

我正在尝试允许用户自定义WPF应用程序中的元素。我的目标是,如果我有一个列出所有表单元素(TextBox、Label等)的列表框,用户可以选择一个表单元素,并设置样式属性,比如说 Label 的前景色应该是橙色,而 TextBox 的前景色应该是黑色,以此类推。根据我想要应用的任何样式,所有的文本框应该看起来都是相同的。

我无法找到一种实现这一点的方法。我已经尝试了一个例子,在运行时可以上传多个预定义的样式。所以,现在我想找到一种在运行时更改不同元素属性的方法。

更新:

我尝试从代码后台创建一个新样式。

XAML

<Label Content="SAMPLE" Style="{DynamicResource Style1}" x:Name="label1" />
<Button Content="Button" Click="Button_Click" />

在后台代码中,即在单击按钮时,我尝试了这个:

Style style = new Style { TargetType = typeof(Label) };
style.Setters.Add(new Setter(Control.ForegroundProperty, Brushes.Black));
Application.Current.Resources["Style1"] = style;

但它没有被更新。

谢谢。


1
从 MSDN:一旦应用了样式,它就被封存并且无法更改。如果您想要动态更改已经应用的样式,那么您必须创建一个新的样式来替换现有的样式。 - Nitesh
你认为这行代码 Application.Current.Resources["Style1"] = style; 会替换你在 XAML 中写的 Style 吗? - Nitesh
这是我从https://dev59.com/i2kv5IYBdhLWcg3wxz2A尝试的一个解决方案。 - ds345
3个回答

35

您必须确保样式位于文件App.xaml中:

<Application x:Class="ChangeStyleHelp.App"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         StartupUri="MainWindow.xaml">

    <Application.Resources>
        <Style x:Key="MyStyle" TargetType="{x:Type Label}">
            <Setter Property="Background" Value="Green" />
        </Style>
    </Application.Resources>
</Application>

代码后台:

private void ChangeStyle_Click(object sender, RoutedEventArgs e)
{
    Style style = new Style 
    { 
        TargetType = typeof(Label) 
    };

    style.Setters.Add(new Setter(Label.BackgroundProperty, Brushes.Aquamarine));

    Application.Current.Resources["MyStyle"] = style;
}   
如果StyleWindow的资源中(Window.Resources),那么您需要写上this或者Window的名称:

private void ChangeStyle_Click(object sender, RoutedEventArgs e)
{
    Style style = new Style 
    { 
        TargetType = typeof(Label) 
    };

    style.Setters.Add(new Setter(Label.BackgroundProperty, Brushes.Aquamarine));

    this.Resources["MyStyle"] = style;
}   

此外,您可以通过以下方式更改样式:使用现有样式并应用于元素。例如:

<Application x:Class="ChangeStyleHelp.App"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         StartupUri="MainWindow.xaml">

    <Application.Resources>
        <Style x:Key="AnotherWayStyle" TargetType="{x:Type Label}">
            <Setter Property="Background" Value="Lavender" />
            <Setter Property="Foreground" Value="OrangeRed" />
        </Style>
    </Application.Resources>
</Application>  

代码后台:

private void AnotherWay_Click(object sender, RoutedEventArgs e)
{
    label1.Style = (Style)Application.Current.Resources["AnotherWayStyle"];
}   

7

你是否尝试过使用资源字典

资源字典

<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<SolidColorBrush x:Key="TextColor" Color="#FF121212"/>
</ResourceDictionary>

XAML控件

<TextBox Text="TextBox" Foreground="{DynamicResource TextColor}" />

动态修改样式代码

     var rd = new ResourceDictionary();
     rd.Add("TextColor", "#FFFFFF");
     Application.Current.Resources.MergedDictionaries.Add(rd);

这将把您的新样式与现有样式合并,改动将自动反映在所有链接到这些样式的控件上。

1
它对我非常有效:

Xaml:

<TreeView x:Name="TreePeople">
    <TreeView.ItemContainerStyle>
        <Style TargetType="{x:Type TreeViewItem}">
            <Setter Property="IsExpanded" Value="True" />
        </Style>
    </TreeView.ItemContainerStyle>
</TreeView> 

c#:

bool Expanded = false; 
// The event subscription method (for a button click)
private void ButtonExpand__Click(object sender, RoutedEventArgs e)
{
    Expanded = !Expanded;
    Style Style = new Style
    {
        TargetType = typeof(TreeViewItem)
    };

    Style.Setters.Add(new Setter(TreeViewItem.IsExpandedProperty, Expanded));
    TreePeople.ItemContainerStyle = Style;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接