C# 在WPF中创建UI设置的正确方法是什么?

C# 在WPF中创建UI设置的正确方法是什么?,c#,wpf,xaml,data-binding,settings,C#,Wpf,Xaml,Data Binding,Settings,我现在正在研究XAML中的一个基本样式,其中包括我的标准HandledWindow类型的模板。 该样式包括一些本地资源,如颜色、字体和其他变量,以便以后在我的样式中重用 我在考虑用户的UI设置,这样他就可以随心所欲地更改颜色和大小。 但后来我发现,更改本地资源不会更改样式本身,而只会更改当前HandledWindow实例的样式,因此这不适合UI设置,因为应用程序中可能会有更多的运行窗口 然后我意识到我必须将变量绑定到我的HandledWindow类的模板,该类将包括所有可变设置作为公共和静态属性

我现在正在研究XAML中的一个基本样式,其中包括我的标准
HandledWindow
类型的模板。 该样式包括一些本地资源,如颜色、字体和其他变量,以便以后在我的样式中重用

我在考虑用户的UI设置,这样他就可以随心所欲地更改颜色和大小。 但后来我发现,更改本地资源不会更改样式本身,而只会更改当前
HandledWindow
实例的样式,因此这不适合UI设置,因为应用程序中可能会有更多的运行窗口

然后我意识到我必须将变量绑定到我的
HandledWindow
类的模板,该类将包括所有可变设置作为公共和静态属性。但随后我遇到了静态属性绑定的问题,因为我无法引发仅适用于实例的
PropertyChanged
事件。窗口本身不会更新其样式

此外,我还试图让样式在不重新启动的情况下立即反应和更新。

WPF是“以资源为中心的”。您可以在资源中定义所有UI样式、画笔和模板,并且在运行时很容易启用应用程序范围的主题更改,这些更改将包含您提到的所有属性。以下是在我的主视图模型通过其设置视图模型从我的设置窗口收到消息后,我如何在主视图模型中执行此操作:

private void ApplyTheme()
{          
    Application.Current.Resources.MergedDictionaries.Clear();

    var rd = new ResourceDictionary { { "Locator", locator } };
    Application.Current.Resources.MergedDictionaries.Add(rd);

    switch (theme)
    {
        case "Blue":
            Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary() { Source = new Uri("/Telerik.Windows.Themes.Office_Blue;component/Themes/System.Windows.xaml", UriKind.RelativeOrAbsolute) });
            Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary() { Source = new Uri("/Telerik.Windows.Themes.Office_Blue;component/Themes/Telerik.Windows.Controls.GridView.xaml", UriKind.RelativeOrAbsolute) });
            Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary() { Source = new Uri("/Telerik.Windows.Themes.Office_Blue;component/Themes/Telerik.Windows.Controls.Input.xaml", UriKind.RelativeOrAbsolute) });
            Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary() { Source = new Uri("/Telerik.Windows.Themes.Office_Blue;component/Themes/Telerik.Windows.Controls.Navigation.xaml", UriKind.RelativeOrAbsolute) });
            Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary() { Source = new Uri("/Telerik.Windows.Themes.Office_Blue;component/Themes/Telerik.Windows.Controls.xaml", UriKind.RelativeOrAbsolute) });
            break;
        case "Summer":
            Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary() { Source = new Uri("/Telerik.Windows.Themes.Summer;component/Themes/System.Windows.xaml", UriKind.RelativeOrAbsolute) });
            Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary() { Source = new Uri("/Telerik.Windows.Themes.Summer;component/Themes/Telerik.Windows.Controls.GridView.xaml", UriKind.RelativeOrAbsolute) });
            Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary() { Source = new Uri("/Telerik.Windows.Themes.Summer;component/Themes/Telerik.Windows.Controls.Input.xaml", UriKind.RelativeOrAbsolute) });
            Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary() { Source = new Uri("/Telerik.Windows.Themes.Summer;component/Themes/Telerik.Windows.Controls.Navigation.xaml", UriKind.RelativeOrAbsolute) });
            Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary() { Source = new Uri("/Telerik.Windows.Themes.Summer;component/Themes/Telerik.Windows.Controls.xaml", UriKind.RelativeOrAbsolute) });
            break;
        }
        Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary() { Source = new Uri("Resources/Brushes.xaml", UriKind.RelativeOrAbsolute) });
        Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary() { Source = new Uri("Resources/ControlTemplates.xaml", UriKind.RelativeOrAbsolute) });
        Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary() { Source = new Uri("Resources/DataTemplates.xaml", UriKind.RelativeOrAbsolute) });
        Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary() { Source = new Uri("Resources/Styles.xaml", UriKind.RelativeOrAbsolute) });
    }
显然,我使用的是Telerik控件,所以我加载了它们的字典,但在方法的底部,您会注意到我也加载了自己的资源,如画笔、样式等


总之,使用WPF对应用程序范围的主题进行更改并不容易。

发布相关代码和XAML。顺便说一句,WPF有,这在恐龙winforms中是完全不存在的,这就是为什么你被迫在winforms中进行各种可怕的黑客攻击,而在WPF中,一切都是美好和快乐的。主题技巧是通过替换当前实例的
HandledWindow
的资源来完成的,我也在想这一点,但是我需要一些可以同时改变其他窗口主题的东西,比如数据绑定,甚至不需要仅仅通过C#代码加载任何XAML页面,为属性设置一个新值,并且可视化UI应该同时更新。我将在几分钟后发布我的代码。注意,这些静态公共属性也应该由UI编辑,这意味着应该有另一个数据绑定来从UI.No设置它。如果希望应用程序范围的主题在
System.Windows.application.Current.Resources
中加载资源字典。我将尝试这样做,目前我正在将基本样式作为应用程序资源加载到条目
ApplicationDefinition
XAML页面中。所以我认为改变整个主题并不难。但是,我如何才能让用户更改特定的UI设置,而不是整个主题,我想让用户通过设置界面(如带有数据绑定的MVVM mechanics)更改特定的UI变量。顺便说一句,我已经发布了相关代码。