WPF--控件模板
以下视频学习笔记:
https://www.bilibili.com/video/BV1gq4y1D76d?p=20&spm_id_from=pageDriver
前言:
wpf的模板有多种方式,可以分为:
控件模板(ControlTemplate),
控件列表模板(ItemsPanelTemplate),
数据模板(DataTemplate)。
其中ControlTemplate和ItemsPanelTemplate都属于控件模板
模板可以放在控件内部,那么只有这个控件才能使用,为了实现共享模板等,我们可以把模板定义在resource里面,所以我们完全可以把以模板代码添加到window.resource中,方便调用
一,按钮控件示例
效果:
1,控件模板和模板触发器
2,模板是控件的Template 属性,Template 是一个ControlTemplate对象
二,TextBox控件:基于现有默认模板编写
效果:
1,两种方式编辑副本
2,模板代码:
<Style x:Key="UserNameTextBoxStyle" TargetType="{x:Type TextBox}"> <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/> <Setter Property="BorderBrush" Value="{StaticResource TextBox.Static.Border}"/> <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/> <Setter Property="BorderThickness" Value="1"/> <Setter Property="KeyboardNavigation.TabNavigation" Value="None"/> <Setter Property="HorizontalContentAlignment" Value="Left"/> <Setter Property="FocusVisualStyle" Value="{x:Null}"/> <Setter Property="AllowDrop" Value="true"/> <Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/> <Setter Property="Stylus.IsFlicksEnabled" Value="False"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type TextBox}"> <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True" CornerRadius="5"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="40"></ColumnDefinition> <ColumnDefinition></ColumnDefinition> </Grid.ColumnDefinitions> <TextBlock Text="" FontFamily="../Assets/IconFont/#iconfont" FontSize="20" Foreground="#ddd" VerticalAlignment="Center" HorizontalAlignment="Center"></TextBlock> <ScrollViewer x:Name="PART_ContentHost" Grid.Column="1" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden" VerticalAlignment="Center" MinHeight="20"/> </Grid> </Border> <ControlTemplate.Triggers> <Trigger Property="IsEnabled" Value="false"> <Setter Property="Opacity" TargetName="border" Value="0.56"/> </Trigger> <Trigger Property="IsMouseOver" Value="true"> <Setter Property="BorderBrush" TargetName="border" Value="{StaticResource TextBox.MouseOver.Border}"/> </Trigger> <Trigger Property="IsKeyboardFocused" Value="true"> <Setter Property="BorderBrush" TargetName="border" Value="{StaticResource TextBox.Focus.Border}"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> <Style.Triggers> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="IsInactiveSelectionHighlightEnabled" Value="true"/> <Condition Property="IsSelectionActive" Value="false"/> </MultiTrigger.Conditions> <Setter Property="SelectionBrush" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}"/> </MultiTrigger> </Style.Triggers> </Style> <Style x:Key="PasswordBoxStyle" TargetType="{x:Type PasswordBox}"> <Setter Property="PasswordChar" Value="●"/> <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/> <Setter Property="BorderBrush" Value="{StaticResource TextBox.Static.Border}"/> <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/> <Setter Property="BorderThickness" Value="1"/> <Setter Property="KeyboardNavigation.TabNavigation" Value="None"/> <Setter Property="HorizontalContentAlignment" Value="Left"/> <Setter Property="FocusVisualStyle" Value="{x:Null}"/> <Setter Property="AllowDrop" Value="true"/> <Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/> <Setter Property="Stylus.IsFlicksEnabled" Value="False"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type PasswordBox}"> <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True" CornerRadius="5"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="40"></ColumnDefinition> <ColumnDefinition></ColumnDefinition> </Grid.ColumnDefinitions> <TextBlock Text="" FontFamily="../Assets/IconFont/#iconfont" FontSize="20" Foreground="#ddd" HorizontalAlignment="Center" VerticalAlignment="Center"></TextBlock> <ScrollViewer x:Name="PART_ContentHost" Focusable="false" Grid.Column="1" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden" VerticalAlignment="Center" MinHeight="20"/> </Grid> </Border> <ControlTemplate.Triggers> <Trigger Property="IsEnabled" Value="false"> <Setter Property="Opacity" TargetName="border" Value="0.56"/> </Trigger> <Trigger Property="IsMouseOver" Value="true"> <Setter Property="BorderBrush" TargetName="border" Value="{StaticResource TextBox.MouseOver.Border}"/> </Trigger> <Trigger Property="IsKeyboardFocused" Value="true"> <Setter Property="BorderBrush" TargetName="border" Value="{StaticResource TextBox.Focus.Border}"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> <Style.Triggers> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="IsInactiveSelectionHighlightEnabled" Value="true"/> <Condition Property="IsSelectionActive" Value="false"/> </MultiTrigger.Conditions> <Setter Property="SelectionBrush" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}"/> </MultiTrigger> </Style.Triggers> </Style> <Style x:Key="ValidationCodeTextBoxStyle" TargetType="{x:Type TextBox}"> <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/> <Setter Property="BorderBrush" Value="{StaticResource TextBox.Static.Border}"/> <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/> <Setter Property="BorderThickness" Value="1"/> <Setter Property="KeyboardNavigation.TabNavigation" Value="None"/> <Setter Property="HorizontalContentAlignment" Value="Left"/> <Setter Property="FocusVisualStyle" Value="{x:Null}"/> <Setter Property="AllowDrop" Value="true"/> <Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/> <Setter Property="Stylus.IsFlicksEnabled" Value="False"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type TextBox}"> <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True" CornerRadius="5"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="40"></ColumnDefinition> <ColumnDefinition Width="188"></ColumnDefinition> <ColumnDefinition Width="80"></ColumnDefinition> </Grid.ColumnDefinitions> <TextBlock Text="" FontFamily="../Assets/IconFont/#iconfont" FontSize="20" Foreground="#ddd" HorizontalAlignment="Center" VerticalAlignment="Center"></TextBlock> <ScrollViewer x:Name="PART_ContentHost" Focusable="false" Grid.Column="1" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden" VerticalAlignment="Center" MinHeight="20"/> <Image Source="../Assets/Images/验证码.jpg" Grid.Column="2"/> </Grid> </Border> <ControlTemplate.Triggers> <Trigger Property="IsEnabled" Value="false"> <Setter Property="Opacity" TargetName="border" Value="0.56"/> </Trigger> <Trigger Property="IsMouseOver" Value="true"> <Setter Property="BorderBrush" TargetName="border" Value="{StaticResource TextBox.MouseOver.Border}"/> </Trigger> <Trigger Property="IsKeyboardFocused" Value="true"> <Setter Property="BorderBrush" TargetName="border" Value="{StaticResource TextBox.Focus.Border}"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> <Style.Triggers> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="IsInactiveSelectionHighlightEnabled" Value="true"/> <Condition Property="IsSelectionActive" Value="false"/> </MultiTrigger.Conditions> <Setter Property="SelectionBrush" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}"/> </MultiTrigger> </Style.Triggers> </Style>
3,引用目标样式
三,字体图标
1,从 www.iconfont.cn 下载字体图标
2,下载下来的.ttf文件复制到项目资源文件夹中:
3,使用:
<Button Height="40" Width="40" Content="" FontFamily="../Assets/IconFont/#iconfont" FontSize="12" ></Button>
4,注意:如果是新ttf文件替换旧的,如果新增的图标没反应,就重启VS
四,统一样式修改
效果:
代码:
五,字典资源
1,新建一个字典资源
2,引用资源
3,使用资源
4,如果按钮的样式都一样,可以把按钮的大小,字体颜色都写入资源中
优化后的资源代码:
5,设置按钮的代码就更简洁了
六,合并资源
<Window.Resources> <ResourceDictionary > <!--合并资源--> <ResourceDictionary.MergedDictionaries> <!--这是引入默认的资源--> <ResourceDictionary Source="../Assets/Styles/DefaultStyle.xaml" ></ResourceDictionary> <!--这是针对当前RadioButton的资源样式--> <ResourceDictionary> <Style TargetType="RadioButton" x:Key="NavButtonStyle"> <Setter Property="Foreground" Value="White"></Setter> <Setter Property="Template" > <Setter.Value> <ControlTemplate TargetType="RadioButton"> <Border Background="Transparent" CornerRadius="8" Name="Back"> <ContentControl Content="{TemplateBinding Content}" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="20,4"></ContentControl> </Border> <!--设置选中的时候的状态--> <ControlTemplate.Triggers> <Trigger Property="IsChecked" Value="True"> <Setter TargetName="Back" Property="Background" Value="#44ffffff"></Setter> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> </ResourceDictionary> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </Window.Resources>
七:搜索框模板和效果
【7.1】效果
【7.2】TextBox模板
<!--控件模板--> <ControlTemplate TargetType="{x:Type TextBox}" x:Key="SearchTextBoxTemplate"> <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True" CornerRadius="10"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="30"></ColumnDefinition> <ColumnDefinition></ColumnDefinition> </Grid.ColumnDefinitions> <TextBlock Text="" FontFamily="../Assets/IconFont/#iconfont" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="#44ffffff" FontSize="16"></TextBlock> <!--默认有内容的时候,显示"请输入搜索内容..."--> <TextBlock Text="请输入搜索内容..." Grid.Column="1" VerticalAlignment="Center" Name="mt" Visibility="Collapsed"></TextBlock> <ScrollViewer Grid.Column="1" x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden" VerticalAlignment="Center"/> </Grid> </Border> <ControlTemplate.Triggers> <Trigger Property="IsEnabled" Value="false"> <Setter Property="Opacity" TargetName="border" Value="0.56"/> </Trigger> <Trigger Property="IsMouseOver" Value="true"> <Setter Property="BorderBrush" TargetName="border" Value="{StaticResource TextBox.MouseOver.Border}"/> </Trigger> <Trigger Property="IsKeyboardFocused" Value="true"> <Setter Property="BorderBrush" TargetName="border" Value="{StaticResource TextBox.Focus.Border}"/> </Trigger> <!--绑定到本身的Text属性上--> <!--没内容的时候Value="",显示这个mt的属性(显示:"请输入搜索内容..."--> <DataTrigger Binding="{Binding Text,RelativeSource={RelativeSource Self}}" Value=""> <Setter TargetName="mt" Property="Visibility" Value="Visible"></Setter> </DataTrigger> </ControlTemplate.Triggers> </ControlTemplate>
【7.2】TextBox 绑定模板
<!--绑定模板:Template="{StaticResource SearchTextBoxTemplate}--> <TextBox Grid.Row="1" HorizontalAlignment="Right" VerticalAlignment="Center" Width="300" Height="32" Template="{StaticResource SearchTextBoxTemplate}" Background="#22000000" Text="{Binding SearchText }" Foreground="White" > </TextBox>
八,单选框数据绑定
引入命名空间
xmlns:converter="clr-namespace:Zhaoxi.CourseManagement.Converter"
<!--在资源里面定义一下,调用的时候就调用这个genderConverter--> <converter:GenderConverter x:Key="genderConverter"/>
<!--RadioButton控件模板--> <ControlTemplate TargetType="RadioButton" x:Key="GenderRadioButtonTemplate"> <Grid> <!--1个RadioButton有2列--> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition/> </Grid.ColumnDefinitions> <!--默认情况下隐藏Visibility="Collapsed"--> <Border Width="14" Height="14" CornerRadius="7" BorderThickness="1" BorderBrush="#007dea" VerticalAlignment="Top" Margin="5,0,0,0"> <Border Width="8" Height="8" CornerRadius="4" Background="White" Name="point" Visibility="Collapsed"/> </Border> <!--第2列,文字部分--> <ContentControl Grid.Column="1" Content="{TemplateBinding Content}" Margin="5,0,0,0"></ContentControl> </Grid> <ControlTemplate.Triggers> <!--如果IsChecked,显示Name为point的标签--> <Trigger Property="IsChecked" Value="True"> <Setter Property="Visibility" Value="Visible" TargetName="point"></Setter> </Trigger> </ControlTemplate.Triggers> </ControlTemplate>
<Grid Grid.Row="1" Margin="20,0"> <!--统一样式设定--> <Grid.Resources> <!--所有TextBlock前景色白色,如果没有反应,就把white删除在编辑下就好--> <Style TargetType="TextBlock"> <Setter Property="Foreground" Value="White"/> <Setter Property="FontSize" Value="14"/> </Style> <!--所有RadioButton前景色白色--> <Style TargetType="RadioButton"> <Setter Property="Foreground" Value="White"/> </Style> </Grid.Resources> <Grid.RowDefinitions> <RowDefinition Height="40"/> <RowDefinition Height="40"/> <RowDefinition Height="40"/> <RowDefinition Height="40"/> </Grid.RowDefinitions> <StackPanel Orientation="Horizontal"> <TextBlock Text="用户名:"/> <TextBlock Text="{Binding UserInfo.UserName}" Margin="10,0,0,0"/> </StackPanel> <StackPanel Orientation="Horizontal" Grid.Row="1"> <TextBlock Text="性 别:"/> <!--调用资源genderConverter--> <RadioButton Content="男" Margin="10,0,0,0" Template="{StaticResource GenderRadioButtonTemplate}" IsChecked="{Binding UserInfo.Gender,Converter={StaticResource genderConverter},ConverterParameter=1}" /> <RadioButton Content="女" Margin="10,0,0,0" Template="{StaticResource GenderRadioButtonTemplate}" IsChecked="{Binding UserInfo.Gender,Converter={StaticResource genderConverter},ConverterParameter=2}"/> </StackPanel> </Grid>
using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Data; namespace Zhaoxi.CourseManagement.Converter { class GenderConverter : IValueConverter { /// <summary> /// modle向view转换 /// </summary> /// <param name="value">model的值</param> /// <param name="targetType"></param> /// <param name="parameter">前端传入的值</param> /// <param name="culture"></param> /// <returns></returns> public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value == null || parameter == null) { return false; } return value.ToString() == parameter.ToString(); //比如:UserInfo.Gender=1,ConverterParameter=1,范围true } /// <summary> /// view向modle转换,点击RadioButton触发这个事件 /// </summary> /// <param name="value"></param> /// <param name="targetType"></param> /// <param name="parameter"></param> /// <param name="culture"></param> /// <returns></returns> public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { return parameter; } } }