【发布时间】:2016-01-30 01:16:53
【问题描述】:
我已经简化了一些代码。 Style 定义更符合我正在处理的实际程序中的内容,而不是原始样本的所有自动生成的绒毛——对于 Window Resource 样本和我试图移动到 w/应用程序资源示例。
我还在应用程序资源示例中“标记”了基于DependencyObject 的绑定到appColors.appColor。我也玩过一些INotifyPropertyChanged,但还没有让它正常工作。我在App 和AppColors 课程中都试过这个。
基于Changing Colors in WPF Style Programmatically,我能够使用转换器和 DependencyProperty 值以编程方式更改文本框的前景色。使用本地 Windows 资源生成的代码如下:
MainWindow.xaml:
<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:Name="LocalWindow" x:Class="ColorLocal.MainWindow"
xmlns:local="clr-namespace:ColorLocal"
Title="MainWindow" Height="122.321" Width="269.87">
<Window.Resources>
<local:ColorToSolidColorBrushConverter x:Key="ColorToSolidColorBrushConverter" />
<Style x:Key="LocalTextBoxStyle" BasedOn="{x:Null}" TargetType="{x:Type TextBox}">
<Setter Property="Foreground" Value="{Binding ElementName=LocalWindow, Path=localColor, Converter={StaticResource ColorToSolidColorBrushConverter}}"/>
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
</Style>
</Window.Resources>
<Grid>
<TextBox x:Name="textBox" HorizontalAlignment="Left" Height="23" Margin="10,10,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120" Style="{DynamicResource LocalTextBoxStyle}"/>
<Button x:Name="btnRed" Content="Red" HorizontalAlignment="Left" Margin="10,47,0,0" VerticalAlignment="Top" Width="75" Click="btnRed_Click"/>
<Button x:Name="btnGreen" Content="Green" HorizontalAlignment="Left" Margin="90,47,0,0" VerticalAlignment="Top" Width="75" Click="btnGreen_Click"/>
<Button x:Name="btBlue" Content="Blue" HorizontalAlignment="Left" Margin="170,47,0,0" VerticalAlignment="Top" Width="75" Click="btBlue_Click"/>
<Button x:Name="btnNewWindow" Content="New Window" HorizontalAlignment="Left" Margin="170,10,0,0" VerticalAlignment="Top" Width="75" Click="btnNewWindow_Click"/>
</Grid>
</Window>
MainWindow.xaml.cs
namespace ColorLocal
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public static readonly DependencyProperty localColorProperty = DependencyProperty.Register("localColor", typeof(Color?), typeof(MainWindow), new PropertyMetadata(Colors.Purple));
public Color? localColor
{
get { return (Color?)GetValue(localColorProperty); }
set { SetValue(localColorProperty, value); }
}
public MainWindow()
{
InitializeComponent();
}
private void btnRed_Click(object sender, RoutedEventArgs e)
{
this.localColor = Colors.Red;
}
private void btnGreen_Click(object sender, RoutedEventArgs e)
{
this.localColor = Colors.Green;
}
private void btBlue_Click(object sender, RoutedEventArgs e)
{
this.localColor = Colors.Blue;
}
private void btnNewWindow_Click(object sender, RoutedEventArgs e)
{
}
}
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;
}
}
}
此代码生成一个对话框,其中包含一个 TextBox,其文本最初为紫色,3 个按钮标记为 Red、Green、&Blue,以及另一个标有新窗口的按钮。按下相应的颜色按钮,更改 TextBox 中文本的颜色。新窗口按钮什么都不做。
我现在要将它移动到 应用程序资源 中,我可以将它分配给不同窗口上的所有控件,并在整个程序中进行颜色更改。我按照附加代码段中的详细说明进行了更改。我最初在 App.xaml.cs 代码中使用 DependencyObject 值时遇到问题,但发现了另一篇关于此的帖子。但是,即使在 MainWindow TextBox 上,TextBox 的前景色仍然是黑色(我还没有编写围绕新窗口按钮按下的逻辑)。
任何想法/方向将不胜感激。
我已经更新了代码示例这个提供的代码更符合实际的编码
App.xaml
<Application
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:Name="LocalApp" x:Class="ColorApp.App"
xmlns:local="clr-namespace:ColorApp"
StartupUri="MainWindow.xaml">
<Application.Resources>
<local:ColorToSolidColorBrushConverter x:Key="ColorToSolidColorBrushConverter" />
<Style x:Key="AppTextBoxStyle" TargetType="{x:Type TextBox}" BasedOn="{x:Null}">
<Setter Property="Foreground" Value="{Binding appColors.appColor, Converter={StaticResource ColorToSolidColorBrushConverter}, ElementName=LocalApp}"/>
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
</Style>
</Application.Resources>
</Application>
App.xaml.cs
namespace ColorApp
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
public AppColors appColors = new AppColors();
}
public class AppColors : DependencyObject
{
public static readonly DependencyProperty appColorProperty = DependencyProperty.Register("appColor",
typeof(Color?), typeof(AppColors), new PropertyMetadata(Colors.Purple));
public Color? appColor
{
get { return (Color?)this.GetValue(appColorProperty); }
set { this.SetValue(appColorProperty, value); }
}
}
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;
}
}
}
MainWindow.xaml
<Window x:Class="ColorApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="122.321" Width="269.87">
<Grid>
<TextBox x:Name="textBox" HorizontalAlignment="Left" Height="23" Margin="10,10,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120" Style="{DynamicResource AppTextBoxStyle}"/>
<Button x:Name="btnRed" Content="Red" HorizontalAlignment="Left" Margin="10,47,0,0" VerticalAlignment="Top" Width="75" Click="btnRed_Click"/>
<Button x:Name="btnGreen" Content="Green" HorizontalAlignment="Left" Margin="90,47,0,0" VerticalAlignment="Top" Width="75" Click="btnGreen_Click"/>
<Button x:Name="btBlue" Content="Blue" HorizontalAlignment="Left" Margin="170,47,0,0" VerticalAlignment="Top" Width="75" Click="btBlue_Click"/>
<Button x:Name="btnNewWindow" Content="New Window" HorizontalAlignment="Left" Margin="170,10,0,0" VerticalAlignment="Top" Width="75" Click="btnNewWindow_Click"/>
</Grid>
</Window>
MainWindow.xaml.cs
namespace ColorApp
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void btnRed_Click(object sender, RoutedEventArgs e)
{
((App)Application.Current).appColors.appColor = Colors.Red;
}
private void btnGreen_Click(object sender, RoutedEventArgs e)
{
((App)Application.Current).appColors.appColor = Colors.Green;
}
private void btBlue_Click(object sender, RoutedEventArgs e)
{
((App)Application.Current).appColors.appColor = Colors.Blue;
}
private void btnNewWindow_Click(object sender, RoutedEventArgs e)
{
}
}
}
【问题讨论】:
-
这主要是一个代码转储,你能把它归结为一个很小的minimal reproducible example,也许开始一个新项目并取出所有额外的东西?
-
嗯,这是一个示例可行的项目,旨在展示我在一个更大的项目中所经历的事情。前半部分是使用本地 Windows 资源样式的工作代码,该样式根据原始问题的输入按预期工作。第二组代码是一个示例,演示了我如何尝试将其作为应用程序资源来完成。程序运行,但文本框颜色与第一个代码集相比没有变化。
-
App本身继承自Application不是依赖对象,我想知道这是否导致了问题。在黑暗中射击:尝试在App上实施INotifyPropertyChanged并在appColor上通知。话虽这么说,你的结构中有一些不稳定的东西,我还不能指手画脚。我认为那里有一对多的间接...如果我是对的,您可以将整个AppColors类扔掉并通知App类。 -
Ok -- 添加 AppColors 是因为另一篇 StackOverflow 文章突出显示 App 类不是基于 DependencyObject 与 MainWindow 不同,这就是为什么我收到“非静态字段需要对象引用”的编译错误、方法或属性”第一篇提到了 cmets。
-
问题是你在
App上绑定到appColor。如果发生变化,则没有通知工具。您可以直接实现INotifyPropertyChanged并丢弃您的辅助构造,或者通过仍需要通知工具的代理以某种方式将其插入其中。