WPF自定義控制元件與樣式(3)-TextBox & RichTextBox & PasswordBox樣式、水印、Label標簽、功能擴展
原文:https://www.cnblogs.com/anding/p/4970845.html一.前言.預覽
申明:WPF自定義控制元件與樣式是一個系列文章,前后是有些關聯的,但大多是按照由簡到繁的順序逐步發布的等,若有不明白的地方可以參考本系列前面的文章,文末附有部分文章鏈接,
本文主要是對文本輸入控制元件進行樣式開發,及相關擴展功能開發,主要內容包括:
- 基本文本框TextBox控制元件樣式及擴展功能,實作了樣式、水印、Label標簽、功能擴展;
- 富文本框RichTextBox控制元件樣式;
- 密碼輸入框PasswordBox控制元件樣式及擴展功能;
效果圖:

二.基本文本框TextBox控制元件樣式及擴展功能
2.1 TextBox基本樣式
樣式代碼如下:
<!--TextBox默認樣式-->
<Style TargetType="{x:Type TextBox}" x:Key="DefaultTextBox">
<Setter Property="ContextMenu" Value="https://www.cnblogs.com/rh-fernando/p/{DynamicResource TextBoxContextMenu}" />
<Setter Property="SelectionBrush" Value="https://www.cnblogs.com/rh-fernando/p/{StaticResource TextSelectionBrush}" />
<Setter Property="FontFamily" Value="https://www.cnblogs.com/rh-fernando/p/{StaticResource FontFamily}" />
<Setter Property="FontSize" Value="https://www.cnblogs.com/rh-fernando/p/{StaticResource FontSize}" />
<Setter Property="BorderThickness" Value="https://www.cnblogs.com/rh-fernando/p/1" />
<Setter Property="MinHeight" Value="https://www.cnblogs.com/rh-fernando/p/26" />
<Setter Property="Width" Value="https://www.cnblogs.com/rh-fernando/p/100" />
<Setter Property="Background" Value="https://www.cnblogs.com/rh-fernando/p/{StaticResource TextBackground}" />
<Setter Property="Foreground" Value="https://www.cnblogs.com/rh-fernando/p/{StaticResource TextForeground}" />
<Setter Property="Padding" Value="https://www.cnblogs.com/rh-fernando/p/0" />
<Setter Property="BorderBrush" Value="https://www.cnblogs.com/rh-fernando/p/{StaticResource ControlBorderBrush}" />
<Setter Property="local:ControlAttachProperty.FocusBorderBrush" Value="https://www.cnblogs.com/rh-fernando/p/{StaticResource FocusBorderBrush}" />
<Setter Property="local:ControlAttachProperty.MouseOverBorderBrush" Value="https://www.cnblogs.com/rh-fernando/p/{StaticResource MouseOverBorderBrush}" />
<Setter Property="VerticalContentAlignment" Value="https://www.cnblogs.com/rh-fernando/p/Center" />
<!-- change SnapsToDevicePixels to True to view a better border and validation error -->
<Setter Property="SnapsToDevicePixels" Value="https://www.cnblogs.com/rh-fernando/p/True" />
<!--英 ['k?r?t] 美 ['k?r?t] 插入符號-->
<Setter Property="CaretBrush" Value="https://www.cnblogs.com/rh-fernando/p/{StaticResource TextForeground}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Grid x:Name="PART_Root">
<Border x:Name="Bg" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
CornerRadius="{TemplateBinding local:ControlAttachProperty.CornerRadius}"
BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" />
<Grid x:Name="PART_InnerGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<!--Label區域-->
<ContentControl x:Name="Label" Margin="1" Template="{TemplateBinding local:ControlAttachProperty.LabelTemplate}"
Content="{TemplateBinding local:ControlAttachProperty.Label}"/>
<!--內容區域-->
<ScrollViewer x:Name="PART_ContentHost" BorderThickness="0" Grid.Column="1" IsTabStop="False" Margin="2"
VerticalAlignment="Stretch" Background="{x:Null}" />
<!--水印-->
<TextBlock x:Name="Message" Padding="{TemplateBinding Padding}" Visibility="Collapsed"
Text="{TemplateBinding local:ControlAttachProperty.Watermark}" Grid.Column="1"
Foreground="{TemplateBinding Foreground}" IsHitTestVisible="False" Opacity="{StaticResource WatermarkOpacity}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Margin="5,2,5,2" />
<!--附加內容區域-->
<Border x:Name="PART_AttachContent" Grid.Column="2" Margin="2" VerticalAlignment="Center" HorizontalAlignment="Center" >
<ContentControl VerticalAlignment="Center" VerticalContentAlignment="Center" Template="{TemplateBinding local:ControlAttachProperty.AttachContent}" />
</Border>
</Grid>
</Grid>
<ControlTemplate.Triggers>
<!--顯示水印-->
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Text}" Value="">
<Setter TargetName="Message" Property="Visibility" Value="https://www.cnblogs.com/rh-fernando/p/Visible" />
</DataTrigger>
<Trigger Property="IsMouseOver" Value="https://www.cnblogs.com/rh-fernando/p/True">
<Setter Property="BorderBrush" Value="https://www.cnblogs.com/rh-fernando/p/{Binding Path=(local:ControlAttachProperty.MouseOverBorderBrush),RelativeSource={RelativeSource Self}}"/>
</Trigger>
<Trigger Property="IsFocused" Value="https://www.cnblogs.com/rh-fernando/p/True">
<Setter Property="BorderBrush" Value="https://www.cnblogs.com/rh-fernando/p/{Binding Path=(local:ControlAttachProperty.FocusBorderBrush),RelativeSource={RelativeSource Self}}"/>
</Trigger>
<!--不可用-->
<Trigger Property="IsEnabled" Value="https://www.cnblogs.com/rh-fernando/p/False">
<Setter TargetName="PART_Root" Property="Opacity" Value="https://www.cnblogs.com/rh-fernando/p/{StaticResource DisableOpacity}" />
</Trigger>
<!--只讀時,禁用PART_AttachContent-->
<Trigger Property="IsReadOnly" Value="https://www.cnblogs.com/rh-fernando/p/True">
<Setter TargetName="PART_AttachContent" Property="IsEnabled" Value="https://www.cnblogs.com/rh-fernando/p/False" />
<Setter TargetName="Bg" Property="Opacity" Value="https://www.cnblogs.com/rh-fernando/p/{StaticResource ReadonlyOpacity}" />
<Setter TargetName="PART_ContentHost" Property="Opacity" Value="https://www.cnblogs.com/rh-fernando/p/{StaticResource ReadonlyOpacity}" />
<Setter TargetName="Label" Property="Opacity" Value="https://www.cnblogs.com/rh-fernando/p/{StaticResource ReadonlyOpacity}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
模板內容主要包含四部分:
- 用于實作Label標簽的預留區域;
- TextBox本身的文本輸入顯示部分;
- 水印顯示部分;
- 功能擴展的預留區域;
其中Label標簽、功能擴展,還有輸入框的不同狀態顯示效果都是通過附加屬性來實作的,其實從本質上附加屬性和控制元件上定義的依賴屬性是同一個概念,有些時候附加屬性會更加方便,對于一些可共用的屬性,就比較方便,這一點怎本文是有體現的,上面代碼使用到的附加屬性代碼:
View Code
2.2 水印效果實作
通過2.1的代碼示例,可以看出,水印是內置了一個TextBlock,用附加屬性ControlAttachProperty.Watermark設定水印內容,在觸發器中檢測,當TextBox中有輸入值,則隱藏水印的TextBlock,使用示例:
<StackPanel>
<TextBox Width="140" Height="40" Margin="3" TextWrapping="Wrap" VerticalScrollBarVisibility="Visible">333333333333333</TextBox>
<TextBox Width="150" Height="30" Margin="3" core:ControlAttachProperty.Watermark="我是水印" core:ControlAttachProperty.CornerRadius="2"></TextBox>
<TextBox Width="150" Height="30" Margin="3" IsReadOnly="True" core:ControlAttachProperty.CornerRadius="15" SnapsToDevicePixels="True" >我是只讀的</TextBox>
<TextBox Width="150" Height="30" Margin="3" IsEnabled="False">IsEnabled="False"</TextBox>
<TextBox Width="150" Height="30" core:ControlAttachProperty.Watermark="我是水印"></TextBox>
</StackPanel>
效果:

2.3 Label標簽實作
參考2.1的代碼,預留了Label的區域,通過設定附加屬性local:ControlAttachProperty.Label設定標簽文本,local:ControlAttachProperty.LabelTemplate設定Label標簽的模板樣式,即可自定義實作Label標簽,自定義樣式:
<!--TextBox包含附加屬性Label的樣式-->
<Style TargetType="{x:Type TextBox}" x:Key="LabelTextBox" BasedOn="{StaticResource DefaultTextBox}">
<Setter Property="local:ControlAttachProperty.LabelTemplate" >
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<Border Width="60" Background="{StaticResource TextLabelBackground}">
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Right" Margin="3" Text="{TemplateBinding Content}"></TextBlock>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
使用示例及效果:
<TextBox Width="200" Height="30" Margin="3" core:ControlAttachProperty.Watermark="請輸入姓名"
Style="{StaticResource LabelTextBox}" core:ControlAttachProperty.Label="姓名:"></TextBox>

2.4 擴展功能及自定義擴展
思路和2.3的Label標簽實作相似,清除文本框內的內容是一個常用需求,我們就線擴展一個這么一個功能的TextBox,通過附加屬性ControlAttachProperty.AttachContent定義擴展功能的模板,模板內定義的是一個按鈕FButton(可參考上一篇,本文末尾附錄中有鏈接)
<!--TextBox包含清除Text按鈕的樣式-->
<Style TargetType="{x:Type TextBox}" x:Key="ClearButtonTextBox" BasedOn="{StaticResource DefaultTextBox}">
<Setter Property="local:ControlAttachProperty.AttachContent">
<Setter.Value>
<ControlTemplate>
<local:FButton FIcon="" Style="{StaticResource FButton_Transparency}" IsTabStop="False" FIconMargin="0"
local:ControlAttachProperty.IsClearTextButtonBehaviorEnabled="True" Command="local:ControlAttachProperty.ClearTextCommand"
CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type TextBox}}}"
Margin="1,3,1,4" FIconSize="14" Foreground="{StaticResource TextForeground}" Cursor="Arrow"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
這里定義的是顯示效果,清除TextBox內容的邏輯代碼如何實作的呢?還是附加屬性:
- ControlAttachProperty.IsClearTextButtonBehaviorEnabled="True" :注入事件到當前Button
- Command="local:ControlAttachProperty.ClearTextCommand":定義Fbutton的命令物件實體Command
- CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type TextBox}}}":把TextBox作為引數傳入
邏輯代碼如下,從代碼不難看出,它是支持多種輸入控制元件的內容清除的,也就是說該擴展功能可以輕松支持其他輸入控制元件,第四節密碼資料的清除也是這樣使用的,
View Code
效果:

當然我們也可以自定義擴展其他功能,如:
<TextBox Width="200" Height="30" Margin="3" core:ControlAttachProperty.Watermark="查詢關鍵詞" IsEnabled="True">
<core:ControlAttachProperty.AttachContent>
<ControlTemplate>
<StackPanel Orientation="Horizontal">
<core:FButton FIcon="" Style="{StaticResource FButton_Transparency}" IsTabStop="False" FIconMargin="0"
FIconSize="18" Margin="1,1,2,3" Foreground="{StaticResource TextForeground}" Cursor="Arrow"/>
<core:FButton FIcon="" Style="{StaticResource FButton_Transparency}" IsTabStop="False" FIconMargin="0"
FIconSize="22" Foreground="{StaticResource TextForeground}" Cursor="Arrow"/>
</StackPanel>
</ControlTemplate>
</core:ControlAttachProperty.AttachContent>
</TextBox>
效果:

由上不難同時實作Label標簽和清除文本內容的樣式:
<!--TextBox包含附加屬性Label,以及ClearText按鈕的樣式-->
<Style TargetType="{x:Type TextBox}" x:Key="LabelClearButtonTextBox" BasedOn="{StaticResource DefaultTextBox}">
<Setter Property="local:ControlAttachProperty.LabelTemplate" >
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<Border Width="60" Background="{StaticResource TextLabelBackground}">
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Right" Margin="3" Text="{TemplateBinding Content}"></TextBlock>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="local:ControlAttachProperty.AttachContent">
<Setter.Value>
<ControlTemplate>
<local:FButton FIcon="" Style="{StaticResource FButton_Transparency}" IsTabStop="False" FIconMargin="0"
local:ControlAttachProperty.IsClearTextButtonBehaviorEnabled="True" Command="local:ControlAttachProperty.ClearTextCommand"
CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type TextBox}}}"
Margin="0,3,1,4" FIconSize="14" Foreground="{StaticResource TextForeground}" Cursor="Arrow"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
2.6 檔案選擇輸入相關擴展
先看看效果,就明白了,
具體實作原理和上面2.4差不多 ,實作了三個檔案、檔案夾選擇相關的功能擴展,樣式代碼:
<!--LabelOpenFileTextBox-->
<Style TargetType="{x:Type TextBox}" x:Key="LabelOpenFileTextBox" BasedOn="{StaticResource LabelClearButtonTextBox}">
<Setter Property="local:ControlAttachProperty.Label" Value="https://www.cnblogs.com/rh-fernando/p/檔案路徑"/>
<Setter Property="local:ControlAttachProperty.Watermark" Value="https://www.cnblogs.com/rh-fernando/p/選擇檔案路徑"/>
<Setter Property="local:ControlAttachProperty.AttachContent">
<Setter.Value>
<ControlTemplate>
<local:FButton FIcon="" Style="{StaticResource FButton_Transparency}" IsTabStop="False" FIconMargin="0"
local:ControlAttachProperty.IsOpenFileButtonBehaviorEnabled="True" Command="local:ControlAttachProperty.OpenFileCommand"
CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type TextBox}}}"
Margin="0,1,0,1" FIconSize="22" Foreground="{StaticResource TextForeground}" Cursor="Arrow"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!--LabelOpenFolderTextBox-->
<Style TargetType="{x:Type TextBox}" x:Key="LabelOpenFolderTextBox" BasedOn="{StaticResource LabelClearButtonTextBox}">
<Setter Property="local:ControlAttachProperty.Label" Value="https://www.cnblogs.com/rh-fernando/p/設定路徑"/>
<Setter Property="local:ControlAttachProperty.Watermark" Value="https://www.cnblogs.com/rh-fernando/p/選擇檔案夾路徑"/>
<Setter Property="local:ControlAttachProperty.AttachContent">
<Setter.Value>
<ControlTemplate>
<local:FButton FIcon="" Style="{StaticResource FButton_Transparency}" IsTabStop="False" FIconMargin="0"
local:ControlAttachProperty.IsOpenFolderButtonBehaviorEnabled="True" Command="local:ControlAttachProperty.OpenFolderCommand"
CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type TextBox}}}"
Margin="0,1,0,1" FIconSize="22" Foreground="{StaticResource TextForeground}" Cursor="Arrow"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!--LabelSaveFileTextBox-->
<Style TargetType="{x:Type TextBox}" x:Key="LabelSaveFileTextBox" BasedOn="{StaticResource LabelClearButtonTextBox}">
<Setter Property="local:ControlAttachProperty.Label" Value="https://www.cnblogs.com/rh-fernando/p/保存路徑"/>
<Setter Property="local:ControlAttachProperty.Watermark" Value="https://www.cnblogs.com/rh-fernando/p/選擇檔案保存路徑"/>
<Setter Property="local:ControlAttachProperty.AttachContent">
<Setter.Value>
<ControlTemplate>
<local:FButton FIcon="" Style="{StaticResource FButton_Transparency}" IsTabStop="False" FIconMargin="0"
local:ControlAttachProperty.IsSaveFileButtonBehaviorEnabled="True" Command="local:ControlAttachProperty.SaveFileCommand"
CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type TextBox}}}"
Margin="0,1,0,1" FIconSize="20" Foreground="{StaticResource TextForeground}" Cursor="Arrow"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
當然實作原理和2.4一樣,都是依賴屬性來實作事件的注入和系結的,所以就不多廢話了:
View Code
三.富文本框RichTextBox控制元件樣式
RichTextBox的樣式比較簡單:
<!--***************************DefaultRichTextBox***************************-->
<Style x:Key="DefaultRichTextBox" TargetType="{x:Type RichTextBox}">
<Setter Property="ContextMenu" Value="https://www.cnblogs.com/rh-fernando/p/{DynamicResource TextBoxContextMenu}" />
<Setter Property="SelectionBrush" Value="https://www.cnblogs.com/rh-fernando/p/{StaticResource TextSelectionBrush}" />
<Setter Property="FontFamily" Value="https://www.cnblogs.com/rh-fernando/p/{StaticResource FontFamily}" />
<Setter Property="FontSize" Value="https://www.cnblogs.com/rh-fernando/p/{StaticResource FontSize}" />
<Setter Property="BorderThickness" Value="https://www.cnblogs.com/rh-fernando/p/1" />
<Setter Property="BorderBrush" Value="https://www.cnblogs.com/rh-fernando/p/{StaticResource ControlBorderBrush}" />
<Setter Property="MinHeight" Value="https://www.cnblogs.com/rh-fernando/p/26" />
<Setter Property="MinWidth" Value="https://www.cnblogs.com/rh-fernando/p/10" />
<Setter Property="Background" Value="https://www.cnblogs.com/rh-fernando/p/{StaticResource TextBackground}" />
<Setter Property="Foreground" Value="https://www.cnblogs.com/rh-fernando/p/{StaticResource TextForeground}" />
<Setter Property="CaretBrush" Value="https://www.cnblogs.com/rh-fernando/p/{StaticResource TextForeground}" />
<Setter Property="local:ControlAttachProperty.FocusBorderBrush" Value="https://www.cnblogs.com/rh-fernando/p/{StaticResource FocusBorderBrush}" />
<Setter Property="local:ControlAttachProperty.MouseOverBorderBrush" Value="https://www.cnblogs.com/rh-fernando/p/{StaticResource MouseOverBorderBrush}" />
<Setter Property="Padding" Value="https://www.cnblogs.com/rh-fernando/p/1" />
<Setter Property="AllowDrop" Value="https://www.cnblogs.com/rh-fernando/p/True" />
<Setter Property="VerticalScrollBarVisibility" Value="https://www.cnblogs.com/rh-fernando/p/Auto" />
<Setter Property="FocusVisualStyle" Value="https://www.cnblogs.com/rh-fernando/p/{x:Null}" />
<Setter Property="ScrollViewer.PanningMode" Value="https://www.cnblogs.com/rh-fernando/p/VerticalFirst" />
<!--該值指示是否啟用了筆勢-->
<Setter Property="Stylus.IsFlicksEnabled" Value="https://www.cnblogs.com/rh-fernando/p/False" />
<!--SnapsToDevicePixels:該值來確定呈現此元素是否應使用特定于設備的像素設定-->
<Setter Property="SnapsToDevicePixels" Value="https://www.cnblogs.com/rh-fernando/p/True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBoxBase}">
<Grid>
<Border x:Name="Bd"
BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}">
<ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="https://www.cnblogs.com/rh-fernando/p/True">
<Setter Property="BorderBrush" Value="https://www.cnblogs.com/rh-fernando/p/{Binding Path=(local:ControlAttachProperty.MouseOverBorderBrush),RelativeSource={RelativeSource Self}}"/>
</Trigger>
<Trigger Property="IsFocused" Value="https://www.cnblogs.com/rh-fernando/p/True">
<Setter Property="BorderBrush" Value="https://www.cnblogs.com/rh-fernando/p/{Binding Path=(local:ControlAttachProperty.FocusBorderBrush),RelativeSource={RelativeSource Self}}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="https://www.cnblogs.com/rh-fernando/p/False">
<Setter TargetName="Bd" Property="Opacity" Value="https://www.cnblogs.com/rh-fernando/p/0.5" />
</Trigger>
<Trigger Property="IsReadOnly" Value="https://www.cnblogs.com/rh-fernando/p/True">
<Setter TargetName="Bd" Property="Opacity" Value="https://www.cnblogs.com/rh-fernando/p/0.85" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
使用實力及效果:

四.密碼輸入框PasswordBox控制元件樣式及擴展功能
密碼輸入控制元件的樣式和第二節文本框TextBox基本一致,就不做詳細的說明了,直接上樣式的代碼,相關邏輯(C#) 代碼和上面是一樣的(復用),
<!--TextBox默認樣式-->
<Style TargetType="{x:Type PasswordBox}" x:Key="DefaultPasswordBox">
<Setter Property="ContextMenu" Value="https://www.cnblogs.com/rh-fernando/p/{DynamicResource TextBoxContextMenu}" />
<Setter Property="SelectionBrush" Value="https://www.cnblogs.com/rh-fernando/p/{StaticResource TextSelectionBrush}" />
<Setter Property="FontFamily" Value="https://www.cnblogs.com/rh-fernando/p/{StaticResource FontFamily}" />
<Setter Property="FontSize" Value="https://www.cnblogs.com/rh-fernando/p/{StaticResource FontSize}" />
<Setter Property="BorderThickness" Value="https://www.cnblogs.com/rh-fernando/p/1" />
<Setter Property="PasswordChar" Value="https://www.cnblogs.com/rh-fernando/p/●"/>
<Setter Property="Height" Value="https://www.cnblogs.com/rh-fernando/p/30" />
<Setter Property="Width" Value="https://www.cnblogs.com/rh-fernando/p/200" />
<Setter Property="Background" Value="https://www.cnblogs.com/rh-fernando/p/{StaticResource TextBackground}" />
<Setter Property="Foreground" Value="https://www.cnblogs.com/rh-fernando/p/{StaticResource TextForeground}" />
<Setter Property="Padding" Value="https://www.cnblogs.com/rh-fernando/p/0" />
<Setter Property="BorderBrush" Value="https://www.cnblogs.com/rh-fernando/p/{StaticResource ControlBorderBrush}" />
<Setter Property="local:ControlAttachProperty.FocusBorderBrush" Value="https://www.cnblogs.com/rh-fernando/p/{StaticResource FocusBorderBrush}" />
<Setter Property="local:ControlAttachProperty.MouseOverBorderBrush" Value="https://www.cnblogs.com/rh-fernando/p/{StaticResource MouseOverBorderBrush}" />
<Setter Property="VerticalContentAlignment" Value="https://www.cnblogs.com/rh-fernando/p/Center" />
<!-- change SnapsToDevicePixels to True to view a better border and validation error -->
<Setter Property="SnapsToDevicePixels" Value="https://www.cnblogs.com/rh-fernando/p/True" />
<!--英 ['k?r?t] 美 ['k?r?t] 插入符號-->
<Setter Property="CaretBrush" Value="https://www.cnblogs.com/rh-fernando/p/{StaticResource TextForeground}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type PasswordBox}">
<Grid x:Name="PART_Root">
<Border x:Name="Bg" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
CornerRadius="{TemplateBinding local:ControlAttachProperty.CornerRadius}"
BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" />
<Grid x:Name="PART_InnerGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<!--Label區域-->
<ContentControl x:Name="Label" Margin="1" Template="{TemplateBinding local:ControlAttachProperty.LabelTemplate}"
Content="{TemplateBinding local:ControlAttachProperty.Label}"/>
<!--內容區域-->
<ScrollViewer x:Name="PART_ContentHost" BorderThickness="0" Grid.Column="1" IsTabStop="False" Margin="2"
VerticalAlignment="Stretch" Background="{x:Null}" />
<!--附加內容區域-->
<Border x:Name="PART_AttachContent" Grid.Column="2" Margin="2" VerticalAlignment="Center" HorizontalAlignment="Center" >
<ContentControl VerticalAlignment="Center" VerticalContentAlignment="Center" Template="{TemplateBinding local:ControlAttachProperty.AttachContent}" />
</Border>
</Grid>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="https://www.cnblogs.com/rh-fernando/p/True">
<Setter Property="BorderBrush" Value="https://www.cnblogs.com/rh-fernando/p/{Binding Path=(local:ControlAttachProperty.MouseOverBorderBrush),RelativeSource={RelativeSource Self}}"/>
</Trigger>
<Trigger Property="IsFocused" Value="https://www.cnblogs.com/rh-fernando/p/True">
<Setter Property="BorderBrush" Value="https://www.cnblogs.com/rh-fernando/p/{Binding Path=(local:ControlAttachProperty.FocusBorderBrush),RelativeSource={RelativeSource Self}}"/>
</Trigger>
<!--不可用-->
<Trigger Property="IsEnabled" Value="https://www.cnblogs.com/rh-fernando/p/False">
<Setter TargetName="PART_Root" Property="Opacity" Value="https://www.cnblogs.com/rh-fernando/p/{StaticResource DisableOpacity}"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!--TextBox包含清除Text按鈕的樣式-->
<Style TargetType="{x:Type PasswordBox}" x:Key="ClearButtonPasswordBox" BasedOn="{StaticResource DefaultPasswordBox}">
<Setter Property="local:ControlAttachProperty.AttachContent">
<Setter.Value>
<ControlTemplate>
<local:FButton FIcon="" Style="{StaticResource FButton_Transparency}" IsTabStop="False" FIconMargin="0"
local:ControlAttachProperty.IsClearTextButtonBehaviorEnabled="True" Command="local:ControlAttachProperty.ClearTextCommand"
CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type PasswordBox}}}"
Margin="1,3,1,4" FIconSize="14" Foreground="{StaticResource TextForeground}" Cursor="Arrow"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!--TextBox包含附加屬性Label的樣式-->
<Style TargetType="{x:Type PasswordBox}" x:Key="LabelPasswordBox" BasedOn="{StaticResource DefaultPasswordBox}">
<Setter Property="local:ControlAttachProperty.LabelTemplate" >
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<Border Width="60" Background="{StaticResource TextLabelBackground}">
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Right" Margin="3" Text="{TemplateBinding Content}"></TextBlock>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!--TextBox包含附加屬性Label,以及ClearText按鈕的樣式-->
<Style TargetType="{x:Type PasswordBox}" x:Key="LabelClearButtonPasswordBox" BasedOn="{StaticResource DefaultPasswordBox}">
<Setter Property="local:ControlAttachProperty.LabelTemplate" >
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<Border Width="60" Background="{StaticResource TextLabelBackground}">
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Right" Margin="3" Text="{TemplateBinding Content}"></TextBlock>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="local:ControlAttachProperty.AttachContent">
<Setter.Value>
<ControlTemplate>
<local:FButton FIcon="" Style="{StaticResource FButton_Transparency}" IsTabStop="False" FIconMargin="0"
local:ControlAttachProperty.IsClearTextButtonBehaviorEnabled="True" Command="local:ControlAttachProperty.ClearTextCommand"
CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type PasswordBox}}}"
Margin="0,3,1,4" FIconSize="14" Foreground="{StaticResource TextForeground}" Cursor="Arrow"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
使用示例及效果:

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/22537.html
標籤:WPF
上一篇:wpf dual monitor
