修改主题资源
您可以自定义视觉元素的主题资源(笔刷、厚度、颜色、样式、模板等),如下所述。
如果您使用DevExpress WPF Controls NuGet包,则应该在计算机上安装DevExpress WPF Controls ,安装包括DevExpress WPF主题源代码。
使用WPF主题设计器
WPF主题设计器是一个独立的工具,允许您基于内置的DevExpress WPF应用程序主题创建自定义主题。
要使用WPF主题设计器更改主题资源,请执行以下步骤:
- 从DevExpress WPF控件单独下载WPF主题设计器。
- 创建自定义主题。
- 使用Inspect Element工具定位要更改其外观的控件元素。
- 修改元素的主题资源。
- 导出带有自定义主题的程序集。
- 在应用程序中引用此程序集。
主题: 主题设计器 - 创建并应用新的自定义主题。
优点
- 可以将修改后的主题导出为程序集。
- 您可以使用Inspect Element工具来定位元素的属性和XAML源代码。
- 自定义主题升级工具允许将自定义主题更新到新版本的DevExpress WPF控件,并解决可能的更新冲突。
- 预览窗口允许将自定义主题应用于DevExpress WPF控件,并查看更改的预览。
缺点
- 您应该从DevExpress WPF控件中单独下载WPF主题设计器 。
在应用程序代码中使用XAML资源
您可以从DevExpress WPF控件源代码中复制主题资源[1]到应用程序中,修改这些主题资源,并在项目中使用它们作为XAML资源。
优点
- 与使用WPF主题设计器相比,修改主题资源的步骤更少。
- 您可以在所有DevExpress WPF主题中使用修改过的主题资源。
部分:将修改后的主题资源应用到应用程序中。
缺点
- 您需要在应用程序的可视化树中找到一个控件元素,并确定应该更改的主题资源[1]。
- 当升级到较新版本的DevExpress WPF控件时,可能会遇到更新问题。
查找元素的主题资源
要访问元素的主题资源[1],请在应用程序的可视化树中找到该元素。您可以使用Visual Studio的Live Visual Tree 、Snoop(在本主题中使用)、WPF主题设计器检查元素工具或其他分析可视化树的工具。
这篇文章展示了如何搜索定义GridColumn过滤器图标外观的模板:
1.在可视化树中找到一个元素
使用Data Grid控件将Snoop工具附加到应用程序上。
按住Ctrl+Shift并将鼠标指针悬停在网格列的过滤器图标上,这个图标由一个带有四个路径项的网格组成。
2.确定要更改的项目
使用项的唯一属性标识要更改的项:控件类型、名称或属性,这个示例使用了Path的Data属性。
3.在主题源代码中找到元素
在要更改其外观的DevExpress WPF主题的源代码中找到元素,您可以使用Visual Studio的内置搜索工具(在本主题中使用)、WPF主题设计器的个人颜色窗口或其他可以搜索文件中的文本的工具。
按照下面的步骤在Office2016White主题的源代码中找到GridColumn过滤器图标的模板。
- 打开Office2016White主题的项目,默认文件夹路径为C:\Program Files\DevExpress 23.1\Components\Sources\XPF\DevExpress.Xpf.Themes\Office2016White\Office2016White.csproj。
- 搜索Path的Data属性值为F1 M 1296.5的元素。
如何修改主题资源的建议
当修改主题资源时,您的修改可能会影响DevExpress WPF控件,并导致异常或不正确的操作等问题。为了避免这些问题,我们建议您遵循以下说明。
- 不要删除名称以PART_开头的元素,也不要更改这些元素的名称/类型,DevExpress WPF控件可以在代码隐藏中使用它们。要hide these elements则将元素的Visibility属性设置为collapse,这种方法在下一点中描述的场景中没有效果。
- DevExpress WPF控件可能会改变PART_编辑器在代码隐藏中的可见性,不要修改这些主题资源中的Visibility属性[1]。要hide these elements则将它们的不透明度属性值设置为0。
- 不要从复杂的笔刷中移除元素,动画的DevExpress WPF控件使用这些元素。
下面的代码片段包含了一个带有GradientStop元素的复杂LinearGradientBrush的例子:
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0"> <GradientStop Color="#FFD1E4FC" Offset="0" /> <GradientStop Color="#FFAED1F6" Offset="1" /> <GradientStop Color="#FFB5D0F1" Offset="0.5" /> <GradientStop Color="#FFA4C5ED" Offset="0.5" /> </LinearGradientBrush>
- DevExpress WPF控件可能包含cs:Name属性,您应该从自定义主题资源中删除它,或者指定以下XML名称空间来忽略它:
<Window ... xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:cs="colorscheme_ignorable_uri" mc:Ignorable="cs"> <Window.Resources> <ControlTemplate x:Key="{dxgt:GridColumnHeaderThemeKey ResourceKey=ControlTemplate}" TargetType="{x:Type dxg:GridColumnHeaderBase}"> <Grid> <!-- ... --> <Border ... cs:Name="Border_0001"/> </Grid> </ControlTemplate> </Window.Resources> </Window>
将修改后的主题资源应用到应用程序中
将修改后的主题资源[1]粘贴到目标元素(控件、窗口或应用程序)的资源中,并选择以下选项之一:
- 要将修改后的资源应用于所有DevExpress WPF主题,请将资源的IsThemeIndependent属性设置为true。下面的代码示例修改了所有DevExpress WPF主题中窗口内所有GridColumnHeaderBase元素的资源:
<Window ... xmlns:dxgt="http://schemas.devexpress.com/winfx/2008/xaml/grid/themekeys"> <Window.Resources> <ControlTemplate x:Key="{dxgt:GridColumnHeaderThemeKey ResourceKey = ColumnFilterTemplate, IsThemeIndependent = true}"> <!-- ... --> </ControlTemplate> </Window.Resources> </Window>
- 要修改specific theme,请指定资源的ThemeName属性,您可以在主题列表主题中找到可用的ThemeName属性值列表(请参阅主题名称列)。下面的代码示例只修改Office2019Colorful主题中的资源:
<Window ... xmlns:dxgt="http://schemas.devexpress.com/winfx/2008/xaml/grid/themekeys"> <Window.Resources> <ControlTemplate x:Key="{dxgt:GridColumnHeaderThemeKey ResourceKey=ColumnFilterTemplate,ThemeName=Office2019Colorful}" TargetType="{x:Type ToggleButton}"> <!-- ... --> </ControlTemplate> </Window.Resources> </Window>
如果您没有指定资源的IsThemeIndependent或ThemeName属性,则该资源仅在DeepBlue主题中应用。
修改主题资源要求
修改后的主题资源[1]应满足以下要求:
1.确保主题资源对其目标元素可见。
2.引用程序集并复制主题资源使用的名称空间。
3.将弹出窗口和消息框中使用的主题资源放在App.xaml资源中。
4.如果主题资源使用静态资源(brush、Converters等),也应该将它们复制到应用程序中。
使用不同主题的不同主题资源
- 为使用的每个主题创建主题资源[1]。
- 为每个创建的主题资源指定ThemeName属性。
您可以在主题列表主题中找到可用的ThemeName属性值列表(请参阅主题名称列)。
下面的代码示例使用Office2013和MetropolisDark应用程序主题的不同模板:
<Window ... xmlns:dxgt="http://schemas.devexpress.com/winfx/2008/xaml/grid/themekeys"> <Window.Resources> <ControlTemplate x:Key="{dxgt:GridColumnHeaderThemeKey ResourceKey=ColumnFilterTemplate,ThemeName=Office2013}" TargetType="{x:Type ToggleButton}"> <!-- ... --> </ControlTemplate> <ControlTemplate x:Key="{dxgt:GridColumnHeaderThemeKey ResourceKey=ColumnFilterTemplate,ThemeName=MetropolisDark}" TargetType="{x:Type ToggleButton}"> <!-- ... --> </ControlTemplate> </Window.Resources> </Window>
使用主题的动态资源
原始主题资源可以使用主题的动态资源:
<Window ... xmlns:dxgt="http://schemas.devexpress.com/winfx/2008/xaml/grid/themekeys"> <Window.Resources> <ControlTemplate ...> <Grid> <Border BorderBrush="{DynamicResource {dxgt:TableViewThemeKey ResourceKey=ColumnChooserBorderBrush}}"> </Grid> </ControlTemplate> <Window.Resources> </Window>
如果您指定修改后的资源的IsThemeIndependent属性,它仍然使用默认主题(DeepBlue)的资源,要使用应用主题中的资源,请执行以下步骤:
- 引用dxi="http://schemas.devexpress.com/winfx/2008/xaml/core/internal" XAML命名空间。
- 将修改后的主题资源的DynamicResource更改为dxi:ThemeResource。themerresource标记扩展动态地将其目标属性设置为目标元素应用的主题中的资源,目标元素必须位于应用程序的可视化树中。
<TargetElement TargetProperty="{dxi:ThemeResource {ThemeKey}}" />
下面的代码示例将Border的(TargetElement) BorderBrush (TargetProperty)属性值设置为目标元素应用的主题中的一个资源(ThemeKey):
<Window ... xmlns:dxi="http://schemas.devexpress.com/winfx/2008/xaml/core/internal" xmlns:dxgt="http://schemas.devexpress.com/winfx/2008/xaml/grid/themekeys"> <Window.Resources> <ControlTemplate ...> <Grid> <Border BorderBrush="{dxi:ThemeResource {dxgt:TableViewThemeKey ResourceKey=ColumnChooserBorderBrush}}"> </Grid> </ControlTemplate> <Window.Resources> </Window>