中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

WPF開發的控件功能擴展

發布時間:2021-07-19 09:08:29 來源:億速云 閱讀:151 作者:chen 欄目:開發技術

這篇文章主要講解了“WPF開發的控件功能擴展”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“WPF開發的控件功能擴展”吧!

目錄
  • No1. 自定義控件模板

  • No2. 重寫控件

  • No3. 附加屬性來試試

  • 總結

文章默認你已經入門WPF了

WPF日常開發,經常遇到默認的控件功能不滿足需求,怎么辦?

No1. 自定義控件模板

平時開發中,經常遇到比較”俗“的需求,嫌棄控件默認的樣子。怎么辦?哈哈,那就整個容唄..... ?!

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

上代碼:

<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>

上外表:

WPF開發的控件功能擴展

No2. 重寫控件

很多情況下,并不是把控件換個外貌就可以解決的,我們不僅要改變外貌,還要改變控件的功能,比如說我們經常用的TextBox控件,正常的功能就是用來輸入的,但更人性化點,我們想要TextBox能告訴我們當前的文本框應該輸入用戶名呢,還是地址呢等等。其實這個就是我們經常看到的水印功能,水印文字肯定要能按需設置,那我們不可能簡單的通過改變下控件模板就可以解決的。

通過需求我們知道,新的帶水印的文本框,至少有個水印這么個依賴屬性,供外部設置。當然新的帶水印文本框和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>

請注意Name為PART_Message的TextBlock就是用來呈現水印提示消息的,同時加了個觸發器,實現這樣的功能:如果未輸入任何內容,則顯示水印,否則就隱藏水印。

控件使用,上代碼:

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

上效果:

WPF開發的控件功能擴展

No3. 附加屬性來試試

重寫控件看似很完美了,真的是這樣嗎?

好了,我的需求又來了,現在文本框提示很perfect,可是我的密碼框PasswordBox也要搞個水印啊?怎么辦?再重寫個帶水印的密碼框?此時有沒有做相同事情的感覺?作為合格的碼農,我們還是要牢記碼農界的警世名言:Don't Repeat Yourself!

此時請回憶下WPF的經典知識點:

控件A放到Grid中,A要支持設置行和列,控件B放到Grid中,B也要支持設置行和列。教程中已經告訴我們不要傻不拉幾在A和B中都去定義行和列的屬性,否則后續C、D......沒完沒了。

此時就是我們應用附加屬性的時候了,在Grid中定義統一的行和列的附加屬性,然后附加應用到A、B上就可以了。

反過來看看我們現在的需求,是不是一樣的套路?我是不是在個公共的地方定義個水印WaterMark附加屬性,然后分別應用到文本框和密碼框就可以了?說對了一半,因為我們文本框和密碼框老的外表沒有顯示水印的地方,所以我們同時還要重新定義下他們的新外表。

話不多說,先上附加屬性定義的代碼:

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>

請和自定義控件中的樣式對比下,其實就是PART_Message對應控件的Text綁定的不一樣了,這樣綁定的是TextBox的附加屬性WaterMarkHelper.WaterMark

上應用代碼:

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

請注意,這樣要手動明確應用定義的樣式資源!

上效果:

WPF開發的控件功能擴展 

課后作業:請依葫蘆畫瓢,實現PasswordBox的水印功能 ?

總結

除了這里列舉的三種方式,其實還可以通過Behavior行為功能,擴展一個控件的功能,比如著名的拖拽功能!寫到這里,我想總結的是:工欲善其事必先利其器!

當我們基礎扎實之后,我們真的可以跳出柵欄,靈活應用!

感謝各位的閱讀,以上就是“WPF開發的控件功能擴展”的內容了,經過本文的學習后,相信大家對WPF開發的控件功能擴展這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

wpf
AI

呼图壁县| 南川市| 开阳县| 治县。| 浦东新区| 隆德县| 阳信县| 涟水县| 静乐县| 临泉县| 凤山县| 都江堰市| 枣强县| 自治县| 安化县| 益阳市| 格尔木市| 乌什县| 九寨沟县| 韶关市| 尉氏县| 永安市| 新巴尔虎右旗| 泸溪县| 龙山县| 苏州市| 陇南市| 剑河县| 吉林市| 玉溪市| 漠河县| 康马县| 佳木斯市| 鹤峰县| 广西| 瑞金市| 那曲县| 垦利县| 江西省| 铜鼓县| 宾阳县|