代码之家  ›  专栏  ›  技术社区  ›  user2950509

从c#更新主题资源?

  •  0
  • user2950509  · 技术社区  · 10 年前

    我有一个空白,用于分析图像,提取两种主要颜色,并替换我在App.xaml中覆盖的“SystemControlForegroundAccentBrush”和“SystemContrrolHighlightAccentBruch”。它工作得很好,只是分析图像需要一些时间,所以一旦我页面中的所有控件都加载完毕,它就会改变颜色。 因此,它们保留了旧的强调颜色。如何让它们动态绑定到该主题资源?

    这是我的app.xaml:

    <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>
    

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

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

    我在Page中有一系列控件。前景设置如下的xaml:

    <TextBlock Foreground="{ThemeResource SystemControlForegroundAccentBrush]"/>
    

    我打电话给你 ColorExtractor.Analyse() 在我的页面.xaml中。cs(在OnNavigatedTo事件中)。我总是可以创建一个在设置颜色后被触发的事件,但我需要找到一种方法来更新页面中所有控件的颜色。

    3 回复  |  直到 10 年前
        1
  •  0
  •   Jon G Stødle    10 年前

    您可以看看模板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

        2
  •  0
  •   Grace Feng    10 年前

    我有一个空白,用于分析图像,提取两种主要颜色,并替换我在App.xaml中覆盖的“SystemControlForegroundAccentBrush”和“SystemContrrolHighlightAccentBruch”。

    首先,我不认为你的代码在应用程序中。xaml可以覆盖 ThemeResource ,你用了这个 Brush 在页面中如下所示:

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

    如果您在 SystemControlForegroundAccentBrush ,您可以在“generic.xaml”文件中找到该资源。

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

    但我认为最好不要做这个手术 OnNavagateTo 事件或 Page.Loaded 事件,UWP中没有刷新方法,我们使用再次导航到此页面进行刷新,因此如果将此操作放入 OnNavagate收件人 事件或 页面.已加载 事件,则每次导航到此页面时,资源都将被覆盖,并且它将再次导航。因此,我将此操作放在按钮单击事件中,如下所示:

    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();
    }
    
        3
  •  0
  •   user2950509    10 年前

    最后,我决定在ColorExtractor中创建一个事件。反恐精英:

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

    然后,在我的主页.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,但这并不需要重新导航到页面。

    推荐文章