以编程方式更改WPF样式中的颜色
本文关键字:颜色 样式 WPF 编程 方式更 | 更新日期: 2023-09-27 18:14:06
首先,我已经在一定程度上完成了我要问的用不同的前景/背景颜色创建不同的样式(例如),然后在代码中执行
Control.Style = new_style
或
this.Resources["MyStyle"] = new_style
我对此很满意,直到我在ComboBox控件中遇到了一个问题,我想通过编程改变下拉按钮上箭头的颜色。这似乎进入了控制模板更改的设置,所以我决定从另一种途径来处理我的颜色更改——使用绑定在样式或控制模板中设置颜色值。所以我创建了一个测试程序,开始简单,并计划对控制模板的变化进行处理,但我还没有得到"简单"的工作。我的测试程序包括一个文本框和一个按钮,我试图改变文本框内的前景色。基本的XML代码是(少了一些行):
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero" x:Class="ColorTest4.MainWindow"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<SolidColorBrush x:Key="FGColor" Color="{Binding fgColor}"/>
</Window.Resources>
<Grid>
<TextBox HorizontalAlignment="Left" Height="23" Margin="10,10,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120" Style="{DynamicResource TextBoxStyle1}">
<TextBox.Resources>
<LinearGradientBrush x:Key="TextBoxBorder" EndPoint="0,20" MappingMode="Absolute" StartPoint="0,0">
<GradientStop Color="#ABADB3" Offset="0.05"/>
<GradientStop Color="#E2E3EA" Offset="0.07"/>
<GradientStop Color="#E3E9EF" Offset="1"/>
</LinearGradientBrush>
<Style x:Key="TextBoxStyle1" BasedOn="{x:Null}" TargetType="{x:Type TextBox}">
<Setter Property="Foreground" Value="{DynamicResource FGColor}"/>
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
<Setter Property="BorderBrush" Value="{StaticResource TextBoxBorder}"/>
<!--<Some Setter Properties & Style.Triggers removed for conciseness >-->
</Style>
</TextBox.Resources>
</TextBox>
<Button Content="Button" HorizontalAlignment="Left" Margin="433,10,0,0" VerticalAlignment="Top" Width="75"/>
</Grid>
</Window>
然后在代码中我有:
private Color pvColor = Colors.Green;
private Color fgColor
{
get { MessageBox.Show("fgColor"); return pvColor; }
}
的想法是,如果我想改变前景的颜色,pvColor只需要改变程序内。
无论出于什么原因,这都不起作用。我希望我只是忽略了一些简单的代码,我还没有看到/找到。如果我在窗口中定义fgColor。资源如下,这是有效的——我得到粉红色的文本:
<Window.Resources>
<SolidColorBrush x:Key="FGColor" Color="Pink"/>
</Window.Resources>
如有任何建议或指导,不胜感激。
感谢更新1:我更新了代码片段以反映颜色而不是画笔的使用。我也尝试过Frank J的INotifyPropertyChanged选项和依赖属性选项,但都没有起作用。依赖性属性抱怨Color不可为空
—Update
我又看了你的代码。
你的问题是,SolidColorBrush的颜色正在改变,但资源本身没有改变,因此改变没有得到传播。
2种可能的解决方案:
1)你可以改变要求,从有一个属性设置笔刷的颜色来改变改变,改变资源本身,这将传播动态资源的变化(按下按钮看到开关):
<Window x:Class="SOTextBoxForeground.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SOTextBoxForeground"
Title="MainWindow" Height="350" Width="525" Name="MyWindow">
<Window.Resources>
<SolidColorBrush x:Key="FGColor" Color="Green"/>
</Window.Resources>
<Grid>
<Grid.Resources>
<Style x:Key="TextBoxStyle1" BasedOn="{StaticResource {x:Type TextBox}}" TargetType="{x:Type TextBox}">
<Setter Property="Foreground" Value="{DynamicResource FGColor}"/>
</Style>
</Grid.Resources>
<TextBox HorizontalAlignment="Left" Height="23" Margin="10,10,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120" Style="{StaticResource TextBoxStyle1}" />
<Button Content="Button" HorizontalAlignment="Left" Margin="433,10,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
</Grid>
</Window>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
this.Resources["FGColor"] = new SolidColorBrush(Colors.Blue);
}
}
2)或者你可以通过转换器直接将样式前景绑定到变量,而不是通过资源(再次按下按钮以查看更改):
<Window x:Class="SOTextBoxForeground.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SOTextBoxForeground"
Title="MainWindow" Height="350" Width="525" Name="MyWindow">
<Window.Resources>
<local:ColorToSolidColorBrushConverter x:Key="ColorToSolidColorBrushConverter" />
</Window.Resources>
<Grid>
<Grid.Resources>
<Style x:Key="TextBoxStyle1" BasedOn="{StaticResource {x:Type TextBox}}" TargetType="{x:Type TextBox}">
<Setter Property="Foreground" Value="{Binding ElementName=MyWindow, Path=pvColor, Converter={StaticResource ColorToSolidColorBrushConverter}}"/>
</Style>
</Grid.Resources>
<TextBox HorizontalAlignment="Left" Height="23" Margin="10,10,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120" Style="{StaticResource TextBoxStyle1}" />
<Button Content="Button" HorizontalAlignment="Left" Margin="433,10,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
</Grid>
</Window>
public class ColorToSolidColorBrushConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
Color? desiredColor = value as Color?;
if (desiredColor != null)
{
return new SolidColorBrush(desiredColor.Value);
}
//Return here your default
return DependencyProperty.UnsetValue;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return DependencyProperty.UnsetValue;
}
}
public partial class MainWindow : Window
{
public static readonly DependencyProperty pvColorProperty = DependencyProperty.Register("pvColor",
typeof(Color?), typeof(MainWindow),
new PropertyMetadata(Colors.Red));
public Color? pvColor
{
get { return (Color?)GetValue(pvColorProperty); }
set { SetValue(pvColorProperty, value); }
}
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
this.pvColor = Colors.Blue;
}
}
public class ColorToSolidColorBrushConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
Color? desiredColor = value as Color?;
if (desiredColor != null)
{
return new SolidColorBrush(desiredColor.Value);
}
//Return here your default
return DependencyProperty.UnsetValue;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return DependencyProperty.UnsetValue;
}
}
对于这两种解决方案,在代码中相应地更改命名空间
SolidColorBrush.Color
期望一个Color
而不是另一个Brush
。
private Color pvColor = Colors.Green;
public Color fgColor
{
get { return pvColor; }
set
{
pvColor = value;
this.OnPropertyChanged("fgColor"); // Make sure you have INotifyPropertyChanged implemented
}
}