WPF自定義控制項與樣式(3)-TextBox & RichTextBox & PasswordBox樣式、水印、Label標簽、功能擴展(轉載)

来源:https://www.cnblogs.com/rh-fernando/archive/2019/10/10/11645827.html
-Advertisement-
Play Games

WPF自定義控制項與樣式(3)-TextBox & RichTextBox & PasswordBox樣式、水印、Label標簽、功能擴展 原文:https://www.cnblogs.com/anding/p/4970845.html 一.前言.預覽 申明:WPF自定義控制項與樣式是一個系列文章,前後 ...


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="{DynamicResource TextBoxContextMenu}" />
        <Setter Property="SelectionBrush" Value="{StaticResource TextSelectionBrush}" />
        <Setter Property="FontFamily" Value="{StaticResource FontFamily}" />
        <Setter Property="FontSize" Value="{StaticResource FontSize}" />
        <Setter Property="BorderThickness" Value="1" />
        <Setter Property="MinHeight" Value="26" />
        <Setter Property="Width" Value="100" />
        <Setter Property="Background" Value="{StaticResource TextBackground}" />
        <Setter Property="Foreground" Value="{StaticResource TextForeground}" />
        <Setter Property="Padding" Value="0" />
        <Setter Property="BorderBrush" Value="{StaticResource ControlBorderBrush}" />
        <Setter Property="local:ControlAttachProperty.FocusBorderBrush" Value="{StaticResource FocusBorderBrush}" />
        <Setter Property="local:ControlAttachProperty.MouseOverBorderBrush" Value="{StaticResource MouseOverBorderBrush}" />
        <Setter Property="VerticalContentAlignment" Value="Center" />
        <!-- change SnapsToDevicePixels to True to view a better border and validation error -->
        <Setter Property="SnapsToDevicePixels" Value="True" />
        <!--英 ['kærət]  美 ['kærət]  插入符號-->
        <Setter Property="CaretBrush" Value="{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="Visible" />
                        </DataTrigger>
                        
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="BorderBrush" Value="{Binding Path=(local:ControlAttachProperty.MouseOverBorderBrush),RelativeSource={RelativeSource Self}}"/>
                        </Trigger>
                        <Trigger Property="IsFocused" Value="True">
                            <Setter  Property="BorderBrush" Value="{Binding Path=(local:ControlAttachProperty.FocusBorderBrush),RelativeSource={RelativeSource Self}}"/>
                        </Trigger>
                        <!--不可用-->
                        <Trigger Property="IsEnabled" Value="False">
                            <Setter TargetName="PART_Root" Property="Opacity" Value="{StaticResource DisableOpacity}" />
                        </Trigger>
                        <!--只讀時,禁用PART_AttachContent-->
                        <Trigger Property="IsReadOnly" Value="True">
                            <Setter TargetName="PART_AttachContent" Property="IsEnabled" Value="False" />
                            <Setter TargetName="Bg" Property="Opacity" Value="{StaticResource ReadonlyOpacity}" />
                            <Setter TargetName="PART_ContentHost" Property="Opacity" Value="{StaticResource ReadonlyOpacity}" />
                            <Setter TargetName="Label" Property="Opacity" Value="{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="&#xe60a;" 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="&#xe60b;"  Style="{StaticResource FButton_Transparency}" IsTabStop="False" FIconMargin="0"
                                            FIconSize="18" Margin="1,1,2,3" Foreground="{StaticResource TextForeground}" Cursor="Arrow"/>
                            <core:FButton FIcon="&#xe628;"  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="&#xe60a;" 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="文件路徑"/>
        <Setter Property="local:ControlAttachProperty.Watermark" Value="選擇文件路徑"/>
        <Setter Property="local:ControlAttachProperty.AttachContent">
            <Setter.Value>
                <ControlTemplate>
                    <local:FButton FIcon="&#xe64e;" 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="設置路徑"/>
        <Setter Property="local:ControlAttachProperty.Watermark" Value="選擇文件夾路徑"/>
        <Setter Property="local:ControlAttachProperty.AttachContent">
            <Setter.Value>
                <ControlTemplate>
                    <local:FButton FIcon="&#xe636;" 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="保存路徑"/>
        <Setter Property="local:ControlAttachProperty.Watermark" Value="選擇文件保存路徑"/>
        <Setter Property="local:ControlAttachProperty.AttachContent">
            <Setter.Value>
                <ControlTemplate>
                    <local:FButton FIcon="&#xe61a;" 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="{DynamicResource TextBoxContextMenu}" />
        <Setter Property="SelectionBrush" Value="{StaticResource TextSelectionBrush}" />
        <Setter Property="FontFamily" Value="{StaticResource FontFamily}" />
        <Setter Property="FontSize" Value="{StaticResource FontSize}" />
        <Setter Property="BorderThickness" Value="1" />
        <Setter Property="BorderBrush" Value="{StaticResource ControlBorderBrush}" />
        <Setter Property="MinHeight" Value="26" />
        <Setter Property="MinWidth" Value="10" />
        <Setter Property="Background" Value="{StaticResource TextBackground}" />
        <Setter Property="Foreground" Value="{StaticResource TextForeground}" />
        <Setter Property="CaretBrush" Value="{StaticResource TextForeground}" />
        <Setter Property="local:ControlAttachProperty.FocusBorderBrush" Value="{StaticResource FocusBorderBrush}" />
        <Setter Property="local:ControlAttachProperty.MouseOverBorderBrush" Value="{StaticResource MouseOverBorderBrush}" />
        <Setter Property="Padding" Value="1" />
        <Setter Property="AllowDrop" Value="True" />
        <Setter Property="VerticalScrollBarVisibility" Value="Auto" />
        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
        <Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst" />
        <!--該值指示是否啟用了筆勢-->
        <Setter Property="Stylus.IsFlicksEnabled" Value="False" />
        <!--SnapsToDevicePixels:該值來確定呈現此元素是否應使用特定於設備的像素設置-->
        <Setter Property="SnapsToDevicePixels" Value="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="True">
                            <Setter Property="BorderBrush" Value="{Binding Path=(local:ControlAttachProperty.MouseOverBorderBrush),RelativeSource={RelativeSource Self}}"/>
                        </Trigger>
                        <Trigger Property="IsFocused" Value="True">
                            <Setter  Property="BorderBrush" Value="{Binding Path=(local:ControlAttachProperty.FocusBorderBrush),RelativeSource={RelativeSource Self}}"/>
                        </Trigger>
                        <Trigger Property="IsEnabled" Value="False">
                            <Setter TargetName="Bd" Property="Opacity" Value="0.5" />
                        </Trigger>
                        <Trigger Property="IsReadOnly" Value="True">
                            <Setter TargetName="Bd" Property="Opacity" Value="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="{DynamicResource TextBoxContextMenu}" />
        <Setter Property="SelectionBrush" Value="{StaticResource TextSelectionBrush}" />
        <Setter Property="FontFamily" Value="{StaticResource FontFamily}" />
        <Setter Property="FontSize" Value="{StaticResource FontSize}" />
        <Setter Property="BorderThickness" Value="1" />
        <Setter Property="PasswordChar" Value="●"/>
        <Setter Property="Height" Value="30" />
        <Setter Property="Width" Value="200" />
        <Setter Property="Background" Value="{StaticResource TextBackground}" />
        <Setter Property="Foreground" Value="{StaticResource TextForeground}" />
        <Setter Property="Padding" Value="0" />
        <Setter Property="BorderBrush" Value="{StaticResource ControlBorderBrush}" />
        <Setter Property="local:ControlAttachProperty.FocusBorderBrush" Value="{StaticResource FocusBorderBrush}" />
        <Setter Property="local:ControlAttachProperty.MouseOverBorderBrush" Value="{StaticResource MouseOverBorderBrush}" />
        <Setter Property="VerticalContentAlignment" Value="Center" />
        <!-- change SnapsToDevicePixels to True to view a better border and validation error -->
        <Setter Property="SnapsToDevicePixels" Value="True" />
        <!--英 ['kærət]  美 ['kærət]  插入符號-->
        <Setter Property="CaretBrush" Value="{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="True">
                            <Setter Property="BorderBrush" Value="{Binding Path=(local:ControlAttachProperty.MouseOverBorderBrush),RelativeSource={RelativeSource Self}}"/>
                        </Trigger>
                        <Trigger Property="IsFocused" Value="True">
                            <Setter  Property="BorderBrush" Value="{Binding Path=(local:ControlAttachProperty.FocusBorderBrush),RelativeSource={RelativeSource Self}}"/>
                        </Trigger>
                        <!--不可用-->
                        <Trigger Property="IsEnabled" Value="False">
                            <Setter TargetName="PART_Root" Property="Opacity" Value="{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="&#xe60a;" 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="&#xe60a;" 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>
複製代碼

使用示例及效果:  


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 有很多人在找客戶過程中遇到了一些問題,有些網站,有些系統裡面經常會把手機號碼的中間四位屏蔽掉 中國的手機號是11位,知道手機的前三位,後四位如何補全中間四位,其實是有軟體可以做到的 前提知道這個號碼是哪個地方的,如果不知道那數據量就太龐大了,先看看軟體圖 因為涉及到號碼的隱私我就塗掉了,使用很簡單, ...
  • //實體類 [Table("invoiceinfo", Schema = "obs")] public class invoice { [Key] public string invoice_num { get; set; } public string merchant_id { get; set... ...
  • 場景 表示時間的數據格式為浮點數,如下: 需要將其格式化為{H:min:s.ms}格式的字元串,效果如下: 註: 博客主頁:https://blog.csdn.net/badao_liumang_qizhi 關註公眾號 霸道的程式猿 獲取編程相關電子書、教程推送與免費下載。 實現 效果 ...
  • 千呼萬喚始出來, asp.net core 3.0 更新簡記 ...
  • 點這裡進入ABP進階教程目錄 更新數據傳輸對象 打開應用層(即JD.CRS.Application)的Course\Dto\GetAllCoursesInput.cs //Course數據傳輸對象(查詢條件) 增加一行代碼 1 using Abp.Application.Services.Dto; ...
  • 一、問題 該問題經常出現在 ABP vNext 框架當中,要復現該問題十分簡單,只需要你註入一個 倉儲,在任意一個地方調用 方法。 例如上面的測試代碼,不出意外就會提示 異常,具體的異常內容信息: 其實已經說得十分明白了,因為你要調用的 已經被釋放了,所以會出現這個異常信息。 二、原因 2.1 為什 ...
  • 整理一下昨天學習的泛型,有不對的地方歡迎指正: 定義一個類,這個類中某些欄位的類型不確定,這些類型可以在構造類時確定下來 2.泛型方法 泛型方法就是定義一個方法,這個方法的參數類型可以是不確定的,當調用這個方法時再去確定這個方法參數的類型。 T作為類型參數也是一個占位符在泛型中,例: 3.泛型解析: ...
  • 前提 入行已經7,8年了,一直想做一套漂亮點的自定義控制項,於是就有了本系列文章。 GitHub:https://github.com/kwwwvagaa/NetWinformControl 碼雲:https://gitee.com/kwwwvagaa/net_winform_custom_contr ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...