欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

WPF開(kāi)發(fā)技巧之花式控件功能擴(kuò)展詳解

 更新時(shí)間:2021年07月18日 11:13:48   作者:小偉06  
這篇文章主要給大家介紹了關(guān)于WPF日常開(kāi)發(fā)之花式控件功能擴(kuò)展的相關(guān)資料,通過(guò)文中這個(gè)例子,我們可以對(duì)WPF的掌握會(huì)更深刻,需要的朋友可以參考下

文章默認(rèn)你已經(jīng)入門WPF了

​ WPF日常開(kāi)發(fā),經(jīng)常遇到默認(rèn)的控件功能不滿足需求,怎么辦?

No1. 自定義控件模板

​ 平時(shí)開(kāi)發(fā)中,經(jīng)常遇到比較”俗“的需求,嫌棄控件默認(rèn)的樣子。怎么辦?哈哈,那就整個(gè)容唄..... 😜!

還記得心靈深處的Button嗎?是不是第一印象就是規(guī)規(guī)矩矩的長(zhǎng)方形,好了,這次我們俗一下,把它變成圓形!

上代碼:

<Button Content="Test1" Width="80" Height="80" FocusVisualStyle="{x:Null}" Background="LightSeaGreen" BorderBrush="DarkBlue">
                <Button.Template>
                    <ControlTemplate TargetType="ButtonBase">
                        <Grid>
                            <Ellipse x:Name="ellipseBorder" StrokeThickness="1" Stroke="{TemplateBinding BorderBrush}" Fill="{TemplateBinding Background}"/>
                            <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Content="{TemplateBinding Content}"/>
                        </Grid>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter Property="Stroke" Value="Orange" TargetName="ellipseBorder"/>
                            </Trigger>
                            <Trigger Property="IsPressed" Value="True">
                                <Setter Property="Stroke" Value="OrangeRed" TargetName="ellipseBorder"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Button.Template>
            </Button>

上外表:

No2. 重寫(xiě)控件

​ 很多情況下,并不是把控件換個(gè)外貌就可以解決的,我們不僅要改變外貌,還要改變控件的功能,比如說(shuō)我們經(jīng)常用的TextBox控件,正常的功能就是用來(lái)輸入的,但更人性化點(diǎn),我們想要TextBox能告訴我們當(dāng)前的文本框應(yīng)該輸入用戶名呢,還是地址呢等等。其實(shí)這個(gè)就是我們經(jīng)??吹降乃」δ埽∥淖挚隙ㄒ馨葱柙O(shè)置,那我們不可能簡(jiǎn)單的通過(guò)改變下控件模板就可以解決的。

​ 通過(guò)需求我們知道,新的帶水印的文本框,至少有個(gè)水印這么個(gè)依賴屬性,供外部設(shè)置。當(dāng)然新的帶水印文本框和TextBox大概的樣子差不多,但我們也要為新的控件定義外貌。

​ 所以第一步,先定義控件的功能,上代碼:

public class WaterMarkTextBox : TextBox
    {
        static WaterMarkTextBox()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(WaterMarkTextBox), new FrameworkPropertyMetadata(typeof(WaterMarkTextBox)));
        }


        public string WaterMark
        {
            get { return (string)GetValue(WaterMarkProperty); }
            set { SetValue(WaterMarkProperty, value); }
        }

        // Using a DependencyProperty as the backing store for WaterMark.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty WaterMarkProperty =
            DependencyProperty.Register("WaterMark", typeof(string), typeof(WaterMarkTextBox), new PropertyMetadata(null));


    }

​ 第二步,再定義控件的樣子,上代碼:

<Style TargetType="{x:Type local:WaterMarkTextBox}">
        <Setter Property="BorderBrush" Value="Black"/>
        <Setter Property="BorderThickness" Value="1"/>
        <Setter Property="VerticalContentAlignment" Value="Center"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:WaterMarkTextBox}">
                    <Grid>
                        <Border Background="{TemplateBinding Background}"
                                BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="{TemplateBinding BorderThickness}">
                        </Border>
                        <ScrollViewer x:Name="PART_ContentHost"
                                      Grid.Column="0"
                                      Margin="0"
                                      Padding="{TemplateBinding Padding}"
                                      VerticalAlignment="Stretch"
                                      Background="{x:Null}"
                                      BorderThickness="0"
                                      IsTabStop="False"
                                      SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                        <TextBlock x:Name="PART_Message"
                                   Margin="4 0"
                                   Padding="{TemplateBinding Padding}"
                                   HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                   VerticalAlignment="Center"
                                   Foreground="Gray"
                                   Text="{TemplateBinding WaterMark}"
                                   Visibility="Collapsed" />
                    </Grid>
                    <ControlTemplate.Triggers>
                        <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Text}" Value="">
                            <Setter TargetName="PART_Message" Property="Visibility" Value="Visible" />
                        </DataTrigger>
                    </ControlTemplate.Triggers>
                    
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

​ 請(qǐng)注意Name為PART_Message的TextBlock就是用來(lái)呈現(xiàn)水印提示消息的,同時(shí)加了個(gè)觸發(fā)器,實(shí)現(xiàn)這樣的功能:如果未輸入任何內(nèi)容,則顯示水印,否則就隱藏水印。

​ 控件使用,上代碼:

 <local:WaterMarkTextBox Margin="20,0,0,0" Width="200" Height="50" WaterMark="Please Input your name"/>

上效果:

No3. 附加屬性來(lái)試試

​ 重寫(xiě)控件看似很完美了,真的是這樣嗎?

​ 好了,我的需求又來(lái)了,現(xiàn)在文本框提示很perfect,可是我的密碼框PasswordBox也要搞個(gè)水印???怎么辦?再重寫(xiě)個(gè)帶水印的密碼框?此時(shí)有沒(méi)有做相同事情的感覺(jué)?作為合格的碼農(nóng),我們還是要牢記碼農(nóng)界的警世名言:Don't Repeat Yourself!

​ 此時(shí)請(qǐng)回憶下WPF的經(jīng)典知識(shí)點(diǎn):

​ 控件A放到Grid中,A要支持設(shè)置行和列,控件B放到Grid中,B也要支持設(shè)置行和列。教程中已經(jīng)告訴我們不要傻不拉幾在A和B中都去定義行和列的屬性,否則后續(xù)C、D......沒(méi)完沒(méi)了。

​ 此時(shí)就是我們應(yīng)用附加屬性的時(shí)候了,在Grid中定義統(tǒng)一的行和列的附加屬性,然后附加應(yīng)用到A、B上就可以了。

​ 反過(guò)來(lái)看看我們現(xiàn)在的需求,是不是一樣的套路?我是不是在個(gè)公共的地方定義個(gè)水印WaterMark附加屬性,然后分別應(yīng)用到文本框和密碼框就可以了?說(shuō)對(duì)了一半,因?yàn)槲覀兾谋究蚝兔艽a框老的外表沒(méi)有顯示水印的地方,所以我們同時(shí)還要重新定義下他們的新外表。

​ 話不多說(shuō),先上附加屬性定義的代碼:

public class WaterMarkHelper
    {
        public static string GetWaterMark(DependencyObject obj)
        {
            return (string)obj.GetValue(WaterMarkProperty);
        }

        public static void SetWaterMark(DependencyObject obj, string value)
        {
            obj.SetValue(WaterMarkProperty, value);
        }

        public static readonly DependencyProperty WaterMarkProperty =
            DependencyProperty.RegisterAttached("WaterMark", typeof(string), typeof(WaterMarkHelper), new PropertyMetadata(null));


    }

上TextBox新的樣式:

<Style x:Key="TextBoxWithWaterMark" TargetType="{x:Type TextBox}">
        <Setter Property="BorderBrush" Value="Black"/>
        <Setter Property="BorderThickness" Value="1"/>
        <Setter Property="VerticalContentAlignment" Value="Center"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type TextBox}">
                    <Grid>
                        <Border Background="{TemplateBinding Background}"
                                BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="{TemplateBinding BorderThickness}">
                        </Border>
                        <ScrollViewer x:Name="PART_ContentHost"
                                      Grid.Column="0"
                                      Margin="0"
                                      Padding="{TemplateBinding Padding}"
                                      VerticalAlignment="Stretch"
                                      Background="{x:Null}"
                                      BorderThickness="0"
                                      IsTabStop="False"
                                      SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                        <TextBlock x:Name="PART_Message"
                                   Margin="4 0"
                                   Padding="{TemplateBinding Padding}"
                                   HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                   VerticalAlignment="Center"
                                   Foreground="Gray"
                                   Text="{TemplateBinding local:WaterMarkHelper.WaterMark}"
                                   Visibility="Collapsed" />
                    </Grid>
                    <ControlTemplate.Triggers>
                        <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Text}" Value="">
                            <Setter TargetName="PART_Message" Property="Visibility" Value="Visible" />
                        </DataTrigger>
                    </ControlTemplate.Triggers>

                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

請(qǐng)和自定義控件中的樣式對(duì)比下,其實(shí)就是PART_Message對(duì)應(yīng)控件的Text綁定的不一樣了,這樣綁定的是TextBox的附加屬性WaterMarkHelper.WaterMark

上應(yīng)用代碼:

 <TextBox Style="{StaticResource TextBoxWithWaterMark}" Margin="20,0,0,0" Width="200" Height="50" local:WaterMarkHelper.WaterMark="Please Input your name"/>

請(qǐng)注意,這樣要手動(dòng)明確應(yīng)用定義的樣式資源!

上效果:

 

課后作業(yè):請(qǐng)依葫蘆畫(huà)瓢,實(shí)現(xiàn)PasswordBox的水印功能 😆

總結(jié)

​ 除了這里列舉的三種方式,其實(shí)還可以通過(guò)Behavior行為功能,擴(kuò)展一個(gè)控件的功能,比如著名的拖拽功能!寫(xiě)到這里,我想總結(jié)的是:工欲善其事必先利其器!

​ 當(dāng)我們基礎(chǔ)扎實(shí)之后,我們真的可以跳出柵欄,靈活應(yīng)用!

到此這篇關(guān)于WPF日常開(kāi)發(fā)之花式控件功能擴(kuò)展的文章就介紹到這了,更多相關(guān)WPF花式控件功能擴(kuò)展內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 深入了解C#多線程安全

    深入了解C#多線程安全

    使用多線程無(wú)法避免的一個(gè)問(wèn)題就是多線程安全。那什么是多線程安全?如何解決多線程安全?本文將通過(guò)一些簡(jiǎn)單的例子為大家詳細(xì)介紹一下多線程相關(guān)的問(wèn)題,感興趣的可以了解一下
    2021-12-12
  • C#?獲取文件夾里所有文件名的詳細(xì)代碼

    C#?獲取文件夾里所有文件名的詳細(xì)代碼

    這篇文章主要介紹了C#?獲取文件夾里所有文件名,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-08-08
  • 基于C# 生成Zip壓縮包代碼

    基于C# 生成Zip壓縮包代碼

    壓縮包制作也是很多項(xiàng)目中需要用到的功能。接下來(lái)通過(guò)本文給大家介紹基于C# 生成Zip壓縮包代碼,對(duì)c生成zip壓縮包相關(guān)知識(shí)感興趣的朋友一起學(xué)習(xí)吧
    2016-04-04
  • c#winform窗口頁(yè)面一打開(kāi)就加載的實(shí)現(xiàn)方式

    c#winform窗口頁(yè)面一打開(kāi)就加載的實(shí)現(xiàn)方式

    這篇文章主要介紹了c#winform窗口頁(yè)面一打開(kāi)就加載的實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • C#多線程基本使用小結(jié)

    C#多線程基本使用小結(jié)

    C#多線程編程涉及Thread、Task、異步和Parallel等工具,Thread類用于創(chuàng)建獨(dú)立線程,通過(guò)Priority屬性設(shè)置優(yōu)先級(jí),而線程池管理線程的調(diào)度和重用,本文給大家介紹C#多線程基本使用小結(jié),感興趣的朋友跟隨小編一起看看吧
    2024-10-10
  • C#編程總結(jié)(一)序列化總結(jié)

    C#編程總結(jié)(一)序列化總結(jié)

    本篇主要介紹了C#序列化總結(jié),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-12-12
  • C#實(shí)現(xiàn)彈窗提示輸入密碼

    C#實(shí)現(xiàn)彈窗提示輸入密碼

    這篇文章主要為大家詳細(xì)介紹了C#實(shí)現(xiàn)彈窗提示輸入密碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • 詳解c# 委托鏈

    詳解c# 委托鏈

    這篇文章主要介紹了c# 委托鏈的相關(guān)資料,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • C# 得到某一天的起始和截止時(shí)間的代碼

    C# 得到某一天的起始和截止時(shí)間的代碼

    自己的制作的單詞學(xué)習(xí)程序中需要得到某一天的起始和截止時(shí)間,找了一下,使用一個(gè)字符串來(lái)轉(zhuǎn)換比較方便
    2011-11-11
  • c# 顏色選擇控件的實(shí)現(xiàn)代碼

    c# 顏色選擇控件的實(shí)現(xiàn)代碼

    這篇文章主要介紹了c# 顏色選擇控件的實(shí)現(xiàn)代碼,幫助大家更好的理解和學(xué)習(xí)使用c#,感興趣的朋友可以了解下
    2021-04-04

最新評(píng)論