从c#更新ThemeResources?

时间:2016-06-19 17:27:44

标签: c# xaml themes uwp

我有一个空白,分析图像,提取两种主色,并取代" SystemControlForegroundAccentBrush"和#34; SystemControlHighlightAccentBrush",我在App.xaml中重写。它运行良好,除了分析图像需要一些时间,因此一旦我的页面中的所有控件都已加载,它就会改变颜色。 结果,他们保持旧的强调色。如何让它们动态绑定到ThemeRessource?

这是我的app.xaml:

$(".arrowback").live("click", function(){
   var userID = this.id;
   alert(userID);
});

这是改变颜色的ColorExtractor.cs类的(非常简化的)部分:

<Application.Resources>
    <ResourceDictionary x:Name="resdic">
        <ResourceDictionary.ThemeDictionaries>
            <ResourceDictionary x:Key="Dark">
                <SolidColorBrush x:Key="SystemControlForegroundAccentBrush"/>
                <SolidColorBrush x:Key="SystemControlHighlightAccentBrush"/>
            </ResourceDictionary>
        </ResourceDictionary.ThemeDictionaries>
    </ResourceDictionary>
</Application.Resources>

我在Page.xaml中有一堆控件,它们的前景设置如下:

public async static void Analyse()
{
    Application.Current.Resources["SystemControlForegroundAccentBrush"] = new SolidColorBrush(color);
    Application.Current.Resources["SystemControlHighlightAccentBrush"] = new SolidColorBrush(color2);
}

我在Page.xaml.cs中调用<TextBlock Foreground="{ThemeResource SystemControlForegroundAccentBrush]"/> (在OnNavigatedTo事件中)。我总是可以创建一个在设置颜色后被触发的事件,但是我需要找到一种方法来更新页面中所有控件的颜色。

3 个答案:

答案 0 :(得分:0)

您可以查看模板10如何进行主题更改,但在他们的情况下,他们提前在资源词典中定义了两个不同的主题。您可以在repo on Github中找到他们的代码,但以下是一些使用的代码:

(Window.Current.Content as FrameworkElement).RequestedTheme = value.ToElementTheme();
Views.Shell.SetRequestedTheme(value, UseBackgroundChecked);

来自here

public static void SetRequestedTheme(ApplicationTheme theme, bool UseBackgroundChecked)
    {

        WindowWrapper.Current().Dispatcher.Dispatch(() =>
        {
            (Window.Current.Content as FrameworkElement).RequestedTheme = theme.ToElementTheme();

            ParseStyleforThemes(theme);

            HamburgerMenu.NavButtonCheckedForeground = NavButtonCheckedForegroundBrush;

            HamburgerMenu.NavButtonCheckedBackground = (UseBackgroundChecked) ?
                NavButtonCheckedBackgroundBrush : NavButtonBackgroundBrush;

            HamburgerMenu.NavButtonCheckedIndicatorBrush = (UseBackgroundChecked) ?
                Colors.Transparent.ToSolidColorBrush() : NavButtonCheckedIndicatorBrush;

            HamburgerMenu.SecondarySeparator = SecondarySeparatorBrush;

            List<HamburgerButtonInfo> NavButtons = HamburgerMenu.PrimaryButtons.ToList();
            NavButtons.InsertRange(NavButtons.Count, HamburgerMenu.SecondaryButtons.ToList());

            List<HamburgerMenu.InfoElement> LoadedNavButtons = new List<HamburgerMenu.InfoElement>();

            foreach (var hbi in NavButtons)
            {
                StackPanel sp = hbi.Content as StackPanel;
                if (hbi.ButtonType == HamburgerButtonInfo.ButtonTypes.Literal) continue;
                ToggleButton tBtn = sp.Parent as ToggleButton;
                Button btn = sp.Parent as Button;

                if (tBtn != null)
                {
                    var button = new HamburgerMenu.InfoElement(tBtn);
                    LoadedNavButtons.Add(button);
                }
                else if (btn != null)
                {
                    var button = new HamburgerMenu.InfoElement(btn);
                    LoadedNavButtons.Add(button);
                    continue;
                }
                else
                {
                    continue;
                }

                Rectangle indicator = tBtn.FirstChild<Rectangle>();
                indicator.Visibility = ((!hbi.IsChecked ?? false)) ? Visibility.Collapsed : Visibility.Visible;

                if (!hbi.IsChecked ?? false) continue;

                ContentPresenter cp = tBtn.FirstAncestor<ContentPresenter>();
                cp.Background = NavButtonCheckedBackgroundBrush;
                cp.Foreground = NavButtonCheckedForegroundBrush;
            }

            LoadedNavButtons.ForEach(x => x.RefreshVisualState());

        });
    }

来自here

答案 1 :(得分:0)

  

我有一个空白,分析图像,提取两种主色,并取代&#34; SystemControlForegroundAccentBrush&#34;和#34; SystemControlHighlightAccentBrush&#34;,我在App.xaml中重写。

首先,我不认为app.xaml中的代码可以覆盖ThemeResource,您在页面中使用了此Brush,如下所示:

<TextBlock Foreground="{ThemeResource SystemControlForegroundAccentBrush}" Text="Hello World!" FontSize="50" />

如果按&#34; F12&#34;在SystemControlForegroundAccentBrush上,您可以在&#34; generic.xaml&#34;中找到此资源。文件。

现在假设您的ColorExtractor.cs类工作正常,ColorExtractor.Analyse()可以覆盖这两个画笔的颜色,并且页面中有很多控件使用这两个资源,刷新页面可以解决您的问题。

但我认为最好不要将此操作放在OnNavagateTo事件或Page.Loaded事件中,UWP中没有刷新方法,我们再次导航到此页面进行刷新,因此,如果将此操作放在OnNavagateTo事件或Page.Loaded事件中,则每次导航到此页面时,资源都将被覆盖并再次导航。所以我把这个操作放在这样的Button click事件中:

public bool Reload()
{
    return Reload(null);
}

private bool Reload(object param)
{
    Type type = this.Frame.CurrentSourcePageType;
    if (this.Frame.BackStack.Any())
    {
        type = this.Frame.BackStack.Last().SourcePageType;
        param = this.Frame.BackStack.Last().Parameter;
    }
    try { return this.Frame.Navigate(type, param); }
    finally
    {
        this.Frame.BackStack.Remove(this.Frame.BackStack.Last());
    }
}

private void Button_Click(object sender, RoutedEventArgs e)
{
    ColorExtractor.Analyse();
    Reload();
}

答案 2 :(得分:0)

最后,我决定在ColorExtractor.cs中创建一个事件:

public static event EventHandler Analysed;
public async static void  Analyse(BitmapImage poster)
{
    //Analyse colors
    Analysed(null, null);
}

然后,在我的MainPage.xaml.cs上:

ColorExtractor.Analyse(bmp);
ColorExtractor.Analysed += (sender, EventArgs) =>
{
    //Set Page foreground color, as a lot of controls are dynamically binded to their parent's foreground brush.
    //If a control isn't automatically binded, all I have to do is say: Foreground="{Binding Foreground, ElementName=page}"
    page.Foreground = Application.Current.Resources["SystemControlForegroundAccentBrush"] as SolidColorBrush;
    page.BorderBrush = Application.Current.Resources["SystemControlHighlightAccentBrush"] as SolidColorBrush;
    //Reload any custom user control that sets it's children's color when it's loaded.
    backdrop.UserControl_Loaded(null, null);
};

所以我实际上并没有直接将我的控件绑定到ForegroundAccentBrush,但这样做无需重新导航到该页面。