Silverlight 中的动态主题






4.67/5 (7投票s)
解释如何动态应用主题到 Silverlight 应用程序
引言
Silverlight 中的主题只是样式的集合。 我们在资源中定义样式。资源的范围可以设置为应用程序级别或 UserControl
级别。范围取决于定义资源的位置。可以在以下位置定义资源
- App.xaml
- 自定义 UserControl.xaml
- 外部资源字典
要在整个应用程序中应用通用的用户界面行为,应在 App.xaml 级别定义资源。可以在 App.xaml 文件的 Application.Resources
部分中定义资源,也可以在外部 .xaml 文件中定义的资源字典中定义资源,然后在 App.xaml 文件中通过 ResourceDictionaries.MergedDictionaries
引用这些资源字典。
我将在外部资源字典中定义我的资源,我将通过 ResourceDictionaries.MergedDictionaries
将这些资源字典引用到 App.xaml 中。
现在,我希望用户通过从主题下拉列表中选择主题来应用他喜欢的主题。在 Silverlight 中,样式是静态资源,可以在 XAML 或代码隐藏中设置。要在代码隐藏中设置样式,应在 App.xaml 或 UserControl.xaml 文件中定义样式,并且必须在代码中逐个处理控件并显式设置样式。
为了克服这个问题,我将在下一节中向您展示一个技巧,以便一次性动态更改控件的样式。
实现
我有一个下拉列表,它将为用户提供不同的主题选项。选择一个主题后,页面中存在的按钮将更改其外观。对于不同的主题,我创建了多个外部资源字典文件,因为要显示的主题有很多。每个资源字典文件代表一个不同的主题。例如,要将绿色主题应用于按钮,有一个名为 GreenTheme.xaml 的文件,该文件对应于该主题。在我的示例中,我有两个主题:黄色和绿色。对于这两个主题,我在 Silverlight 项目中的 Themes 文件夹下分别有两个资源字典文件 GreenTheme.xaml 和 YellowTheme.xaml。默认情况下,我想将绿色主题应用于应用程序,因此我通过使用 ResourceDictionaries.MergedDictionaries
在 App.xaml 中引用了 GreenTheme.xaml 文件。当用户更改对黄色主题的偏好时,我将引用 YellowTheme.xaml 文件。
以下是关于外部资源字典 .xaml 文件的几件事需要记住
- 资源字典文件的“生成操作”属性应设置为“内容”,因为我希望资源文件成为应用程序包的一部分,并且不应嵌入程序集中。
- “复制到输出目录”应设置为“如果较新则复制”。
- “自定义工具”应设置为空。
一旦用户从主题 Comboxbox
中选择了新主题,ComboBox_SelectionChanged
事件将触发,我将发现用户在该事件中选择了哪个主题。该事件的 SelectionChangedEventArgs
将为我提供有关 RemovedItems
(先前选定的项目)和 AddedItems
(新选定的项目)的信息。使用 RemovedItems
,我将找出以前的主题是什么,并将其从应用程序的 MergedDictionary
中删除。并使用 AddedItem
,我将在 MergedDictionary
中添加新的资源字典。
主题资源字典 .xaml 文件将具有为应用程序中的所有控件定义的默认样式。因此,一旦从应用程序资源中删除了先前的资源字典并添加了新的资源字典,控件将采用在新主题文件中定义的默认样式。因此,在这种情况下,无需逐个处理每个控件并显式设置样式,因为默认样式将自动应用。
Using the Code
下面的代码显示了如何动态更改样式。只需将 ComboBox_SelectionChanged
事件处理程序附加到您页面上主题组合框的 selection changed 事件。下面的代码将删除先前选定的主题,并将新选定的主题添加到应用程序资源中。有关实施的更多详细信息,请阅读随附的文章代码。
private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (e.RemovedItems.Count > 0)
{
ComboBoxItem removedComboBoxItem = e.RemovedItems[0] as ComboBoxItem;
if (removedComboBoxItem != null)
{
ResourceDictionary res =
Application.Current.Resources.MergedDictionaries.Where
(q => q.Source.OriginalString ==
removedComboBoxItem.Tag.ToString()).FirstOrDefault();
if (res != null)
{
Application.Current.Resources.MergedDictionaries.Remove(res);
}
}
}
if (e.AddedItems.Count > 0)
{
ComboBoxItem addedComboBoxItem = e.AddedItems[0] as ComboBoxItem;
if (addedComboBoxItem != null)
{
ResourceDictionary res =
Application.Current.Resources.MergedDictionaries.Where
(q => q.Source.OriginalString ==
addedComboBoxItem.Tag.ToString()).FirstOrDefault();
if (res == null)
{
Uri stylePath = new Uri
(addedComboBoxItem.Tag.ToString(), UriKind.Relative);
ResourceDictionary newResource = new ResourceDictionary();
newResource.Source = stylePath;
Application.Current.Resources.MergedDictionaries.Add(newResource);
}
}
}
}
结论
这个技巧将允许用户根据自己的偏好更改样式,甚至可以将用户偏好保存在数据库中,以便当用户下次登录时,他将看到他喜欢的主题。