我正在从后台代码更新应用ThemeResource
。它正在更改应用程序主题,但TextBox BorderBrush
属性未得到更新。
我有一个用于MyBorderBrush
和Dark
的自定义资源Light
,已在App.xaml中定义。
Xaml:
<StackPanel>
<TextBox PlaceholderText="My PlaceholderText" Height="100" Width="500" HorizontalAlignment="Center" Style="{StaticResource NoHighlightTextBoxStyle}" BorderBrush="{Binding IsError, Converter={ThemeResource BorderBrushColorConverter}}" VerticalAlignment="Center" ></TextBox>
<Button Content="Change Theme" Click="Button_Click"></Button>
</StackPanel>
后面的代码:
private void Button_Click(object sender, RoutedEventArgs e)
{
this.RequestedTheme = this.RequestedTheme == ElementTheme.Light ? ElementTheme.Dark : ElementTheme.Light;
}
编辑
我认为问题可能出在代码后面或定义了资源,所以我只分享了最少的代码以重现问题。但是正如@Ashiq指出的那样,问题出在TextBox上。实际上,问题是我将BorderBrush
属性绑定到转换器以获取正确的值,但是在更改主题时,边框颜色没有更改。
转换器:
public class BorderBrushColorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
var isError = value as bool? ?? false;
return isError
? Application.Current.Resources["MyBorderBrushMandatory"] as SolidColorBrush
: Application.Current.Resources["MyBorderBrush"] as SolidColorBrush;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
App.xaml
<ResourceDictionary x:Key="Light" >
<Color x:Key="MyBorder">#6b6b6b</Color>
<SolidColorBrush x:Key="MyBorderBrush" Color="{ThemeResource MyBorder}" />
<Color x:Key="MyBorderMandatory">#ff0000</Color>
<SolidColorBrush x:Key="MyBorderBrushMandatory" Color="{ThemeResource MyBorderMandatory}" />
</ResourceDictionary>
<ResourceDictionary x:Key="Dark" >
<Color x:Key="MyBorder">#c85332</Color>
<SolidColorBrush x:Key="MyBorderBrush" Color="{ThemeResource MyBorder}" />
<Color x:Key="MyBorderMandatory">#FFD700</Color>
<SolidColorBrush x:Key="MyBorderBrushMandatory" Color="{ThemeResource MyBorderMandatory}" />
</ResourceDictionary>
答案 0 :(得分:2)
您不应该将Brush绑定到TextBox
的{{1}}上,这意味着您已经为BorderBrush
设置了固定的Brush值。当您在xaml中使用BorderBrush
和Binding
时,它将“ MyBorderBrushMandatory”或“ MyBorderBrush”资源中的IValueConverter
值分配给SolidColorBrush
,这是一个静态值并且不会根据主题的更改而更改。简而言之,就是将红色固定的BorderBrush
设置为SolidColorBrush
,与动态主题资源无关。
如果您希望在更改主题时更改BorderBrush
中的BorderBrush
,则只需将xaml TextBox
绑定代码替换为主题资源参考:
TextBox
反之,如果您想在主题更改时使用绑定来更改<TextBox PlaceholderText="My PlaceholderText" Height="100" Width="500"
HorizontalAlignment="Center"
BorderBrush="{ThemeResource MyBorderBrushMandatory}"
VerticalAlignment="Center" ></TextBox>
中的BorderBrush
,则应使TextBox
属性实现IsError
,同时,您应该订阅ActualThemeChanged事件以更改INotifyPropertyChanged
属性的值,以从IsError
获取SolidColorBrush
的值,然后更新UI。
以下是取决于您上面的代码的示例:
MainPage.xaml:
BorderBrushColorConverter
MainPage.xaml.cs:
<Page.Resources>
<local:BorderBrushColorConverter x:Key="BorderBrushColorConverter"/>
</Page.Resources>
<StackPanel>
<TextBox PlaceholderText="My PlaceholderText" Height="100" Width="500" HorizontalAlignment="Center"
BorderBrush="{Binding IsError, Converter={StaticResource BorderBrushColorConverter}}"
VerticalAlignment="Center" ></TextBox>
<Button Content="Change Theme" Click="Button_Click"></Button>
</StackPanel>
---更新---
让我们谈谈您的样本。
首先,我们都知道您是通过从App.xaml获取应用程序资源来设置public sealed partial class MainPage : Page,INotifyPropertyChanged
{
public MainPage()
{
this.InitializeComponent();
this.DataContext = this;
this.ActualThemeChanged += MainPage_ActualThemeChanged;
}
public event PropertyChangedEventHandler PropertyChanged;
private void MainPage_ActualThemeChanged(FrameworkElement sender, object args)
{
IsError = !IsError;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
this.RequestedTheme = this.RequestedTheme == ElementTheme.Light ? ElementTheme.Dark : ElementTheme.Light;
}
private void OnPropertyChanged(string Name)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(Name));
}
}
private bool? isError=true;
public bool? IsError
{
get
{
return isError;
}
set
{
isError = value;
OnPropertyChanged("IsError");
}
}
}
的{{1}}的。在您的Page2.xaml.cs中,使用以下代码,
TextBox
此代码仅设置UIElement(及其子元素)用于确定资源的UI主题,也就是说,该代码仅设置页面的主题,而不设置应用程序。默认情况下,您的应用使用用户在Windows设置中设置的主题(设置>个性化>颜色>选择默认应用模式)运行,并且您还可以设置应用的RequestedTheme属性来覆盖用户默认设置并指定使用了主题。
作为 Remarks 部分:
主题只能在启动应用程序时设置,而不能在运行时设置。在应用程序运行时尝试设置RequestedTheme会引发异常(Microsoft .NET代码为NotSupportedException)。如果您为用户提供了选择属于应用程序UI的主题的选项,则必须将设置保存在应用程序数据中并在应用程序重新启动时应用。
因此,当您更改页面的BorderBrush
时,这不会影响应用程序的RequestedTheme,仍然是您在示例的App.xaml中设置的应用程序的RequestedTheme,作为代码,
this.RequestedTheme = App.SelectedTheme;
因此,当您使用代码RequestedTheme
获取应用程序资源时,它仍将获取“ Light”主题资源。与您使用ThemeResource的地方不同。对于此问题,主题资源不是您想要的,您应该在资源中设置一些其他的Color Brush,然后使用StaticResource在页面的资源设置上获取不同的Color Brush资源。
---更新2 ---
这是一个简单的解决方案,只需在App.xaml中添加应用程序资源,
RequestedTheme="Light"
在BorderBrushColorConverter.cs中,更改Application.Current.Resources
方法,
<Application.Resources>
<Color x:Key="MyBorder">#6b6b6b</Color>
<SolidColorBrush x:Key="MyBorderBrush" Color="{StaticResource MyBorder}" />
<Color x:Key="MyBorderMandatory">#ff0000</Color>
<SolidColorBrush x:Key="MyBorderBrushMandatory" Color="{StaticResource MyBorderMandatory}" />
<Color x:Key="MyBorderDark">#c85332</Color>
<SolidColorBrush x:Key="MyBorderBrushDark" Color="{StaticResource MyBorderDark}" />
<Color x:Key="MyBorderMandatoryDark">#FFD700</Color>
<SolidColorBrush x:Key="MyBorderBrushMandatoryDark" Color="{StaticResource MyBorderMandatoryDark}" />
...
</Application.Resources>
在Page2.xaml中,更改为静态资源引用,
Convert
答案 1 :(得分:1)
您正在运行时更改动态主题。因此,将StaticResource更改为ThemeResource。就是这样。
来自
BorderBrush="{StaticResource MyBorderBrush}"
到
BorderBrush="{ThemeResource MyBorderBrush}"
谢谢。