将鼠标悬停在按钮,列标题,组合框等上时,它们都会变成漂亮的Microsoft蓝色。
我宁愿他们为我的企业绿色树立漂亮的阴影。
有没有办法针对我的应用程序或按窗口全局更改此颜色。
如果失败,我是否需要针对每种控件类型进行更改?
答案 0 :(得分:1)
您必须为每个控件定义一个Style
。这是因为视觉效果和视觉状态是由每个控件的内部ControlTemplate
定义的。
但是您可以通过重用模板和级联样式来显着减少工作量。
要允许轻松进行颜色主题设置和集中式自定义,您应该创建一个资源来定义主题的所有相关颜色:
ColorResources.xaml
<ResourceDictionary>
<!-- Colors -->
<Color x:Key="HighlightColor">DarkOrange</Color>
<Color x:Key="DefaultControlColor">LightSeaGreen</Color>
<Color x:Key="ControlDisabledTextColor">Gray</Color>
<Color x:Key="BorderColor">DarkGray</Color>
<Color x:Key="MouseOverColor">LightSteelBlue</Color>
<!-- Brushes -->
<SolidColorBrush x:Key="HighlightBrush" Color="{StaticResource HighlightColor}" />
<SolidColorBrush x:Key="ControlDisabledTextBrush" Color="{StaticResource ControlDisabledColor}" />
<SolidColorBrush x:Key="BorderBrush" Color="{StaticResource BorderColor}" />
<SolidColorBrush x:Key="MouseOverBrush" Color="{StaticResource MouseOverColor}" />
</ResourceDictionary>
您可以将以下样式的模板添加到 App.xaml 文件:
App.xaml
<Application>
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/File/Path/To/ColorResources.xaml" />
</ResourceDictionary.MergedDictionaries>
...
</ResourceDictionary>
</Application.Resources>
</Application>
要覆盖GridView
或DataGrid
中所选行的颜色,您只需要覆盖这些控件使用的默认画笔SystemColors.HighlightBrush
:
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}"
Color="{StaticResource HighlightColor}" />
要覆盖控件的默认颜色,例如DatGrid
的列标题,您只需覆盖这些控件使用的默认画笔SystemColors.ControlBrush
:
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}"
Color="{StaticResource DefaultControlColor}" />
对于像ContentControls
或Button
这样的简单ListBoxItem
,您可以共享一个公用的ControlTemplate
。共享的ControlTemplate
将协调视觉状态:
<ControlTemplate x:Key="BaseContentControlTemplate"
TargetType="ContentControl">
<Border BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}">
<ContentPresenter/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="{StaticResource ControlDisabledTextBrush}" />
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Opacity" Value="0.7" />
<Setter Property="Background" Value="{StaticResource MouseOverBrush}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
此基本模板将使用基本样式应用。这样可以进行简单的链接(样式继承),并可以将BaseContentControlTemplate
重用于Button
或ListBoxItem
等不同的控件:
<Style x:Key="BaseContentControlStyle"
TargetType="ContentControl">
<Setter Property="Template" Value="{StaticResource BaseContentControlTemplate}" />
</Style>
某些ContentControl
,例如Button
,可能需要其他状态,例如Pressed
。您可以通过创建一种基本样式来扩展其他基本的视觉状态,例如以ButtonBase
为目标,并且可以与从ButtonBase
派生的任何控件一起使用:
<Style x:Key="BaseButtonStyle"
TargetType="ButtonBase"
BasedOn="{StaticResource BaseContentControlStyle}">
<Style.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="{StaticResource HighlightBrush}" />
</Trigger>
</Style.Triggers>
</Style>
要应用此基本样式,您必须显式定位控件。您可以使用这种样式来添加更具体的视觉状态或布局,例如ListBoxItem.IsSelcted
,ToggleButton.IsChecked
或DataGridColumnHeader
:
<!-- Buttons -->
<Style TargetType="Button" BasedOn="{StaticResource BaseButtonStyle}" />
<Style TargetType="ToggleButton" BasedOn="{StaticResource BaseButtonStyle}">
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Background" Value="{StaticResource HighlightBrush}" />
</Trigger>
</Style.Triggers>
</Style>
<!- ListBox -->
<Style TargetType="ListBoxItem" BasedOn="{StaticResource BaseContentControlStyle}">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="{StaticResource HighlightBrush}" />
</Trigger>
</Style.Triggers>
</Style>
<!-- ListView -->
<Style TargetType="ListViewItem" BasedOn="{StaticResource {x:Type ListBoxItem}}" />
<!--
GridView
Since GridViewColumnHeader is also a ButtonBase we can extend existing style
-->
<Style TargetType="GridViewColumnHeader" BasedOn="{StaticResource BaseButtonStyle}" />
<Style x:Key="BaseGridViewStyle" TargetType="ListViewItem">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="{StaticResource HighlightBrush}" />
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{StaticResource {x:Static SystemColors.HighlightBrushKey}}" />
</Trigger>
</Style.Triggers>
</Style>
<!--
DataGrid
Since DataGridColumnHeader is also a ButtonBase we can extend existing style
-->
<Style TargetType="DataGridColumnHeader"
BasedOn="{StaticResource BaseButtonStyle}">
<Setter Property="BorderThickness" Value="1,0" />
<Setter Property="BorderBrush" Value="{StaticResource BorderBrush}" />
</Style>
其他更复杂的组成控件,例如ComboBox
,TreeView
或MenuItem
,需要分别覆盖控件的模板。由于这些控件由其他控件组成,因此通常也必须覆盖此控件的样式。例如,ComboBox
由TextBox
,ToggleButton
和Popup
组成。
您可以在Microsoft Docs: Control Styles and Templates上找到它们的样式。
这是将主题添加到应用程序中的非常简单和基本的方法。了解控件的继承树有助于创建可重用的基本样式。重用样式有助于减少定位和自定义每个控件的工作量。
将所有视觉资源(如颜色或图标)定义在一个位置,可以轻松地对其进行修改,而不必分别了解/修改每个控件。
答案 1 :(得分:0)
如果您查看默认样式(https://docs.microsoft.com/en-us/dotnet/framework/wpf/controls/button-styles-and-templates),就会发现每种样式都使用static resources
声明颜色。
因此,要完成您的项目,您将不得不覆盖存储颜色的这些static resources
。
不幸的是,这在WPF
中是不可能的(之前已经有人问过:Override a static resource in WPF)。
因此,您唯一的解决方案是为每个控件编写一个单独的Style
并重新声明颜色。