【问题标题】:Change Theme Dynamically Telerik WPF动态更改主题 Telerik WPF
【发布时间】:2019-01-31 12:32:25
【问题描述】:

我需要允许用户在使用 Telerik WPF 控件创建的应用程序中动态更改主题。

我正在为我的 XAML 中的每个 Telerik 控件设置绑定,如下所示:

XAML:

telerik:StyleManager.Theme="{Binding SelectedSMTheme, Mode=TwoWay}"

视图模型:

    private Theme selectedSMTheme;
    public Theme SelectedSMTheme
    {
        get
        {
            return selectedSMTheme;
        }
        set
        {
            selectedSMTheme = value;
            RaisePropertyChange("SelectedSMTheme");
        }
    }

并在用户选择主题时更改此SelectedSMTheme

改变主题:

SelectedSMTheme = new Expression_DarkTheme();

有没有其他方法可以在运行应用程序时更改 Telerik 控件的主题。因为,这里我需要为整个应用程序中的每个控件指定telerik:StyleManager.Theme

【问题讨论】:

    标签: c# wpf telerik themes


    【解决方案1】:

    您可以使用StyleManager.ApplicationTheme 设置初始主题。设置此属性会影响应用程序中的所有控件。

    您的 App.xaml.cs 构造函数应如下所示:

    public partial class App : Application
    {
        public App()
        {
            StyleManager.ApplicationTheme = new Expression_DarkTheme();
            this.InitializeComponent();
        }
    }
    

    要在运行时切换主题,您应该清除应用程序资源并添加新资源。

    private void btnChangeTheme_Click(object sender, RoutedEventArgs e)
    {
        Application.Current.Resources.MergedDictionaries.Clear();
        Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary()
        {
            Source = new Uri("/Telerik.Windows.Themes.Green;component/Themes/System.Windows.xaml", UriKind.RelativeOrAbsolute)
        });
        Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary()
        {
            Source = new Uri("/Telerik.Windows.Themes.Green;component/Themes/Telerik.Windows.Controls.xaml", UriKind.RelativeOrAbsolute)
        });
        Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary()
        {
            Source = new Uri("/Telerik.Windows.Themes.Green;component/Themes/Telerik.Windows.Controls.Input.xaml", UriKind.RelativeOrAbsolute)
        });
    }
    

    您必须记住从位于安装文件夹中的 Binaries.NoXaml 文件夹中添加所需的程序集(在我的例子中是:C:\Program Files (x86)\Progress\Telerik UI for WPF R2 2018\Binaries.NoXaml):

    • Telerik.Windows.Controls.dll
    • Telerik.Windows.Controls.Input.dll
    • 主题程序集,在我的例子中是:Telerik.Windows.Themes.Expression_Dark.dllTelerik.Windows.Themes.Green.dll

    请阅读以下文章了解更多信息:

    https://docs.telerik.com/devtools/wpf/styling-and-appearance/stylemanager/common-styling-apperance-setting-theme-wpf

    https://docs.telerik.com/devtools/wpf/styling-and-appearance/how-to/styling-apperance-themes-runtime

    【讨论】:

    • 谢谢。但是那样的话,我必须重新运行我的应用程序,对吗?如果不关闭并重新打开它,我认为它不会起作用。所以,我在控制级别设置主题并更改它。但是这样做,需要很好地照顾 XAML,这看起来有点乏味,我正在寻找替代方案......
    • @UpendharSingirikonda 请再次检查我的答案。
    • 再次感谢您。但是,由于某些原因,当我将解决方案嵌入到另一个应用程序时,我无法拥有 app.xaml。因此,我将尝试使用 this.resources.mergedict ... 除了向 XAML 中的每个控件添加主题的开销之外,与这种方法相比,我的初始方法在稳定性和性能方面是否也很好?哪种方式更稳定、更可靠、更高效?
    • @UpendharSingirikonda 我认为使用应用程序资源的解决方案是正确的方法。您的代码库会更清晰,负责应用程序主题的代码将在一个地方。
    • 好的,谢谢。但是,当我有时引用 NoXAML Dlls 时,我的视图没有呈现,并且我遇到了一些问题,比如很少有控件没有动态更改主题等......我会检查
    【解决方案2】:

    我正在使用与 kmatyaszek 提供的类似解决方案,除了,我在 ComboBox 中进行:

     private void StyleCombo_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var selectedTheme = StyleCombo.SelectedItem as ThemeNames;
            Application.Current.Resources.MergedDictionaries.Clear();
    
            // XAML
    
            Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary
            {
                Source = new Uri("/Telerik.Windows.Themes." + selectedTheme.Value + ";component/Themes/System.Windows.xaml", UriKind.RelativeOrAbsolute)
            });
            Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary
            {
                Source = new Uri("/Telerik.Windows.Themes." + selectedTheme.Value + ";component/Themes/Telerik.Windows.Controls.xaml", UriKind.RelativeOrAbsolute)
            });
            Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary
            {
                Source = new Uri("/Telerik.Windows.Themes." + selectedTheme.Value + ";component/Themes/Telerik.Windows.Controls.Input.xaml", UriKind.RelativeOrAbsolute)
            });
            Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary
            {
                Source = new Uri("/Telerik.Windows.Themes." + selectedTheme.Value + ";component/Themes/Telerik.Windows.Controls.Navigation.xaml", UriKind.RelativeOrAbsolute)
            });
            Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary
            {
                Source = new Uri("/Telerik.Windows.Themes." + selectedTheme.Value + ";component/Themes/Telerik.Windows.Controls.Data.xaml", UriKind.RelativeOrAbsolute)
            });
            Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary
            {
                Source = new Uri("/Telerik.Windows.Themes." + selectedTheme.Value + ";component/Themes/Telerik.Windows.Controls.DataVisualization.xaml", UriKind.RelativeOrAbsolute)
            });
            Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary
            {
                Source = new Uri("/Telerik.Windows.Themes." + selectedTheme.Value + ";component/Themes/Telerik.Windows.Controls.Docking.xaml", UriKind.RelativeOrAbsolute)
            });
            Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary
            {
                Source = new Uri("/Telerik.Windows.Themes." + selectedTheme.Value + ";component/Themes/Telerik.Windows.Controls.GridView.xaml", UriKind.RelativeOrAbsolute)
            });
            Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary
            {
                Source = new Uri("/Telerik.Windows.Themes." + selectedTheme.Value + ";component/Themes/Telerik.Windows.Controls.Pivot.xaml", UriKind.RelativeOrAbsolute)
            });
            Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary
            {
                Source = new Uri("/Telerik.Windows.Themes." + selectedTheme.Value + ";component/Themes/Telerik.Windows.Controls.PivotFieldList.xaml", UriKind.RelativeOrAbsolute)
            });
            Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary
            {
                Source = new Uri("/Telerik.Windows.Themes." + selectedTheme.Value + ";component/Themes/Telerik.Windows.Controls.VirtualGrid.xaml", UriKind.RelativeOrAbsolute)
            });
    }
    

    您在 cmets 部分中说过,某些控件不会动态更改 - 这是 NoXaml 库的已知问题。我可以向您推荐的是手动为这些控件设置参数。就我而言,它看起来像这样:

    // Main Grid
    
            if (selectedTheme.Name == "Visual Studio 2013 Dark")
            {
                VisualStudio2013Palette.LoadPreset(VisualStudio2013Palette.ColorVariation.Dark);
                App.StronaGlowna.MainGrid.Background = (SolidColorBrush)new BrushConverter().ConvertFrom("#FF1E1E1E");
            }
    
            if (selectedTheme.Name == "Visual Studio 2013 Blue")
            {
                VisualStudio2013Palette.LoadPreset(VisualStudio2013Palette.ColorVariation.Blue);
            }
    
            if (selectedTheme.Name == "Visual Studio 2013")
            {
                VisualStudio2013Palette.LoadPreset(VisualStudio2013Palette.ColorVariation.Light);
                App.StronaGlowna.MainGrid.Background = Brushes.White;
            }
    
    
    
            if (selectedTheme.Name == "Dark")
            {
                VisualStudio2013Palette.LoadPreset(VisualStudio2013Palette.ColorVariation.Dark);
                App.StronaGlowna.MainGrid.Background = (SolidColorBrush)new BrushConverter().ConvertFrom("#FF3D3D3D");
            }
    
            if (selectedTheme.Name == "Green")
            {
                GreenPalette.LoadPreset(GreenPalette.ColorVariation.Dark);
                App.StronaGlowna.MainGrid.Background = (SolidColorBrush)new BrushConverter().ConvertFrom("#FF1D1E21");
            }
    
            if (selectedTheme.Name == "Green Light")
            {
                GreenPalette.LoadPreset(GreenPalette.ColorVariation.Light);
                App.StronaGlowna.MainGrid.Background = (SolidColorBrush)new BrushConverter().ConvertFrom("#FFE0E0E0");
            }
    
            if (selectedTheme.Name == "Vista" ||
                selectedTheme.Name == "Visual Studio 2013 Blue" || selectedTheme.Name == "Office Black" ||
                selectedTheme.Name == "Office Blue" ||
                selectedTheme.Name == "Office Silver" || selectedTheme.Name == "Summer" ||
                selectedTheme.Name == "Transparent" || selectedTheme.Name == "Windows 7")
            {
                App.StronaGlowna.MainGrid.Background = Brushes.White;
            }
    

    Telerik 支持在 1 张支持票中向我提供了此解决方案。您可以在文档中找到大多数十六进制颜色的控件,例如 this one is for Office2013 theme。另外,请记住,某些 WPF 控件不受样式的影响(我认为其中一个示例是 TextBox),因此如果您使用的是普通 WPF 控件,它们可能保持不变并需要您对新颜色进行硬编码。

    【讨论】:

      猜你喜欢
      • 2012-06-23
      • 2011-01-13
      • 1970-01-01
      • 1970-01-01
      • 2012-02-14
      • 1970-01-01
      • 2011-12-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多