Обновление системных кистей (стилей) на лету в Windown Phone 8.1

Рейтинг: 2Ответов: 1Опубликовано: 16.04.2015

Необходимо обновить цвет системных элементов на лету, т.е. такие как цвет переключателя, цвет выделения листбокса, и подобное. Я нашёл системные кисти, которыми, прописав в app.xaml, в ресурсах, я изменил цвет (при загрузке приложения), но изменение этих кистей из кода c# на лету не даёт должного эффекта. Как можно перезагрузить стили/обновить элементы?

Мне нужно нечто подобное как в стандартном почтовом клиенте, там в настройках можно сменить цвет фона, и соответственно там меняются и цвета элементов, мгновенно.

Вот как я пытался это сделать:

App.xaml:

<Application
    x:Class="App2.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App2">
    <Application.Resources>
        <Color x:Key="MainBrush">#FF009999</Color>
        <SolidColorBrush x:Key="ProgressBarIndeterminateForegroundThemeBrush" Color="{ThemeResource MainBrush}"/>
        <SolidColorBrush x:Key="ToggleSwitchCurtainBackgroundThemeBrush" Color="{ThemeResource MainBrush}"/>
        <SolidColorBrush x:Key="SliderTrackDecreaseBackgroundThemeBrush" Color="{ThemeResource MainBrush}"/>
        <SolidColorBrush x:Key="ListBoxItemSelectedBackgroundThemeBrush" Color="{ThemeResource MainBrush}"/>
        <SolidColorBrush x:Key="TextSelectionHighlightColorThemeBrush" Color="{ThemeResource MainBrush}"/>
        <SolidColorBrush x:Key="SliderThumbBackgroundThemeBrush" Color="{ThemeResource MainBrush}"/>
        <SolidColorBrush x:Key="SliderThumbBorderThemeBrush" Color="{ThemeResource MainBrush}"/>
        <SolidColorBrush x:Key="ListBoxItemPointerOverForegroundThemeBrush" Color="White" />
        <SolidColorBrush x:Key="ListBoxItemPressedForegroundThemeBrush" Color="White" />
        <SolidColorBrush x:Key="ListBoxItemSelectedForegroundThemeBrush" Color="White" />
        <SolidColorBrush x:Key="ListBoxItemSelectedPointerOverBackgroundThemeBrush" Color="Transparent"/>
        <SolidColorBrush x:Key="ListBoxItemDisabledForegroundThemeBrush" Color="Transparent"/>
        <SolidColorBrush x:Key="ListBoxItemPointerOverBackgroundThemeBrush" Color="Transparent"/>
        <SolidColorBrush x:Key="ButtonPressedBackgroundThemeBrush" Color="Transparent"/>
        <SolidColorBrush x:Key="ListBoxItemPressedBackgroundThemeBrush" Color="Transparent"/>
    </Application.Resources>
</Application>

MainPage.xaml:

<Grid>
    <StackPanel>
        <Slider Value="50"/>
        <ListBox SelectedIndex="1" Background="Transparent">
            <TextBlock Foreground="White" Text="TEXT"/>
            <TextBlock Foreground="White" Text="TEXT"/>
            <TextBlock Foreground="White" Text="TEXT"/>
        </ListBox>
        <ToggleSwitch IsOn="True"/>
        <ProgressBar Height="10" Margin="0,20" IsIndeterminate="True"/>
        <Rectangle Height="30">
            <Rectangle.Fill>
                <SolidColorBrush x:Name="RectBrush" Color="{ThemeResource MainBrush}"></SolidColorBrush>
            </Rectangle.Fill>
        </Rectangle>
        <Button Click="ButtonBase_OnClick" HorizontalAlignment="Center" Margin="0,60,0,0" Content="ИЗМЕНИТЬ ЦВЕТ ВСЕГО ЭТОГО"/>
    </StackPanel>
</Grid>

MainPage.cs:

private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
    var c = Color.FromArgb(255, 200, 0, 200);
    RectBrush.Color = c; // прямой способ, естественно работает
    Application.Current.Resources["MainBrush"] = c;
    Application.Current.Resources["ProgressBarIndeterminateForegroundThemeBrush"] = c;
    Application.Current.Resources["ToggleSwitchCurtainBackgroundThemeBrush"] = c;
    Application.Current.Resources["SliderTrackDecreaseBackgroundThemeBrush"] = c;
    Application.Current.Resources["ListBoxItemSelectedBackgroundThemeBrush"] = c;
    Application.Current.Resources["TextSelectionHighlightColorThemeBrush"] = c;
    Application.Current.Resources["SliderThumbBackgroundThemeBrush"] = c;
    Application.Current.Resources["SliderThumbBorderThemeBrush"] = c;
}

Ответы

▲ 3Принят

ThemeResource работает как StaticResource, а не как DynamicResource, то есть значение не перевычисляется, если значение в словаре поменяется. И уж конечно, не отлавливаются изменения свойств объектов в словаре.

ThemeResource предполагает, что ресурсы располагаются не в корне Application.Resources, а в отдельных словарях ресурсов ThemeDictionaries. Во всех темах набор ключей должен быть идентичен. На данный момент поддерживаются две темы: Light, Dark, а также вариации HighContrast. При изменении Application.RequestedTheme значения, полученные от ThemeResource, будут перевычислены. См. ResourceDictionary and XAML resource references (ResourceDictionary и ссылки на ресурсы XAML).

Аналог DynamicResource в WinRT-XAML отсутствует. У вас два пути:

  1. Завести глобальную вью-модель со свойством типа SolidColorBrush AccentColorBrush и во вью биндиться к ней. Биндинги отработают при изменении свойства, и цвета изменятся.

  2. Требовать перезагрузки приложения; при загрузке задавать цвет, выбранный пользователем.

Учтите, что первый способ может сказаться на производительности, если у вас сложные вьюхи.