前言
建议在开发前把项目用到的颜色、前景、背景、字体、转换器、公共样式都提取到公共文件中。
项目实战
全局样式引用
正确写法
不要让项目出现多层ResourceDictionary.MergedDictionaries
嵌套,会出现运行的时候找不到资源的情况。
1 | <Application |
错误写法
注意
下面的这种多层
ResourceDictionary.MergedDictionaries
的写法,会导致明明开发的时候资源都设置成全局的了,运行的时候找不到资源。
这里把引用都放在了ResCommon.xaml文件中,Application引用该文件
1 | <Application |
ResCommon.xaml
这个文件用来引用其他文件及设置默认的样式。
1 | <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:views="clr-namespace:Z.Views;assembly=Z"> |
全局变量
定义
我们可以定义一些全局使用的颜色,字体等
ResCommonBase.xaml
1 | <ResourceDictionary |
字体
1 | <FontFamily x:Key="UnidreamLed">pack://application:,,,/Font/#UniDreamLED</FontFamily> |
使用
1 | <TextBlock |
使用
前景背景
1 | <TextBlock |
字体
1 | <Setter Property="FontSize" Value="{StaticResource FontSizeNomal}" /> |
下面的写法是错误的,在开发时不报错运行时会报错。
1 | <Setter Property="Background" Value="{StaticResource PrimaryColor}" /> |
全局转换器
ResCommonConverter.xaml
1 | <ResourceDictionary |
组件样式
ResStyleWin.xaml
1 | <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> |
ResStyleButton.xaml
1 | <ResourceDictionary |
概念
样式生效范围
根据生效范围从大到小依次为
- Application.Resources(所有页面生效)
- Window.Resources(当前页面生效)
- 组件内设置(当前组件生效)
Resources
1 | <Window.Resources> |
或者
1 | <Window.Resources> |
组件内设置
1 | <TextBlock Text="组件样式"> |
全部生效和引用生效
全部生效
1 | <Style TargetType="TextBlock"> |
注意
只要不设置
x:Key
,那么这个样式就会对所生效范围的所有组件生效,要只对某个生效就要设置x:Key
。全部生效的尽量不要设置太基础的组件,比如如果设置了
TextBlock
,所有的Button
的文字样式也会变化。
设置x:Key
后必须引用才能生效
1 | <Style x:Key="ZTextBlock" TargetType="TextBlock"> |
引用
1 | <TextBlock |
样式和模板
设置样式的时候我们可以设置样式和模板。
1 | <Style |
自定义组件
项目下添加Resources
文件夹,添加以下文件
简单的按钮示例
1 | <Window.Resources> |
使用
1 | <Button Style="{StaticResource JianButton}" /> |
自定义TextBox
1 | <Style x:Key="ZRoundTextBox" |
输入的地方使用:
1 | <ScrollViewer x:Name="PART_ContentHost" VerticalContentAlignment="Center" /> |
它负责显示 TextBox 的内容。这样可以确保在应用自定义样式后,仍然能够输入和显示文本值。
自定义ListBoxItem
/Resources/StyleListBoxItem.xaml
1 | <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> |
/Resources/OverwrideDefaultControlStyles.xaml
1 | <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> |
使用
1 | <ListBox |
报错
System.Windows.Data Error: 4 : Cannot find source for binding with reference ‘RelativeSource FindAncestor, AncestorType=’System.Windows.Controls.ItemsControl’, AncestorLevel=’1’’. BindingExpression:Path=HorizontalContentAlignment; DataItem=null; target element is ‘ComboBoxItem’ (Name=’’); target property is ‘HorizontalContentAlignment’ (type ‘HorizontalAlignment’)
原因是ListBoxItem必须包含下面的两个属性
1 |
|
and use it:
1 | <ListView ItemContainerStyle="{StaticResource ZItemContainerStyle}"/> |
内部裁剪的Border
1 | using System; |
调用方式
引用
1 | xmlns:util="clr-namespace:ZJClassTool.Utils" |
使用
1 | <Views:ZClippingBorder |
自定义滚动条
/Resources/StyleScrolllview.xaml
1 | <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> |
全局样式设置
/Resources/OverwrideDefaultControlStyles.xaml
1 | <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> |
自定义ComboBox
/Resources/StyleComboBox.xaml
1 | <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> |
使用方式
1 | <ComboBox |
问题
样式不生效
我们知道设置启动页有两种方式
- 添加窗口
生成操作
设置为ApplicationDefinition
- 添加cs代码文件,Main方法中运行窗口
但是用以下代码的方式创建窗口,设置的全局样式是不生效的,只有通过StartupUri="Wins/Welcome.xaml"
设置启动页才能使全局样式生效
1 | public partial class MyApp : Application |
但是通过StartupUri
只能设置唯一的启动页,怎么办呢?
我们可以添加一个欢迎页面作为中间页面,这个页面再决定跳转到那个页面,这样设置的全局样式就生效了。