更新ResourceTheme不会反映在UWP App中的TextBox BorderBrush上

时间:2018-09-19 05:49:37

标签: c# xaml uwp

我正在从后台代码更新应用ThemeResource。它正在更改应用程序主题,但TextBox BorderBrush属性未得到更新。

我有一个用于MyBorderBrushDark的自定义资源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>

2 个答案:

答案 0 :(得分:2)

您不应该将Brush绑定到TextBox的{​​{1}}上,这意味着您已经为BorderBrush设置了固定的Brush值。当您在xaml中使用BorderBrushBinding时,它将“ 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}"

谢谢。