<ul id="qxxfc"><fieldset id="qxxfc"><tr id="qxxfc"></tr></fieldset></ul>


      前言

      我在學(xué)習(xí)WPF的早期,對(duì)依賴屬性理解一直都非常的不到位,其惡果就是,我每次在寫依賴屬性的時(shí)候,需要翻過去的代碼來復(fù)制黏貼。

      相信很多朋友有著和我相同的經(jīng)歷,所以這篇文章希望能幫助到那些剛剛開始學(xué)依賴屬性的朋友。

      那些[討厭]的依賴屬性的講解文章

      初學(xué)者肯定會(huì)面臨一件事,就是百度,谷歌,或者M(jìn)SDN來查看依賴屬性的定義和使用,而這些文章雖然都寫的很好,但,那是相對(duì)于已經(jīng)學(xué)會(huì)使用依賴屬性的朋友而言。

      而對(duì)于初學(xué)者而言,說是誤導(dǎo)都不過分。

      比如,官網(wǎng)的這篇文章
      https://docs.microsoft.com/zh-cn/dotnet/framework/wpf/advanced/dependency-properties-overview

      <https://docs.microsoft.com/zh-cn/dotnet/framework/wpf/advanced/dependency-properties-overview>

      介紹依賴屬性是這樣。
      public static readonly DependencyProperty IsSpinningProperty =
      DependencyProperty.Register( "IsSpinning", typeof(Boolean), typeof(MyCode) );
      public bool IsSpinning { get { return (bool)GetValue(IsSpinningProperty); } set
      { SetValue(IsSpinningProperty, value); } }
      他做了一個(gè)定義,然后告訴你,依賴屬性的定義格式如此。

      如果你是個(gè)初學(xué)者,你想不疑惑都很難。因?yàn)闆]人能把這種定義給背下來。


      其結(jié)果就是,你要和我當(dāng)初一樣,每次定義依賴屬性,都要去復(fù)制黏貼。但這并不是最大的惡果,最大的惡果是,因?yàn)樘^復(fù)雜的定義,讓你放棄了對(duì)他理解,就記住了依賴屬性要復(fù)制黏貼,從而導(dǎo)致了,你喪失了對(duì)依賴屬性靈活運(yùn)用的能力。

      正確的理解依賴屬性

      如何正確的理解依賴屬性呢?

      很簡(jiǎn)單,拆分一下就可以理解了。

      現(xiàn)在我們來拆分依賴屬性,首先拆分他的定義,將依賴和屬性拆分。

      我們先看屬性,如下,我們定義了一個(gè)屬性。
      private bool _IsSpinning; public bool IsSpinning { get { return _IsSpinning; }
      set { _IsSpinning = value; } }
      然后我們使用DependencyProperty類定義一個(gè)對(duì)象,這個(gè)對(duì)象將作為IsSpinning屬性的依賴,如下:
      public static readonly DependencyProperty IsSpinningProperty
      然后,我們?cè)趯⑦@個(gè)依賴對(duì)象,注冊(cè)到屬性IsSpinning的所在類上,如下:
      DependencyProperty.Register( "IsSpinning", typeof(bool), typeof(你的屬性所在的類的名稱));
      從注冊(cè)代碼中,我們可以看到,他注冊(cè)了三個(gè)信息:

      1,當(dāng)前DependencyProperty類定義的對(duì)象IsSpinningProperty,依賴于屬性IsSpinning。

      2,對(duì)象IsSpinningProperty的依賴類型與屬性IsSpinning的類型一樣都是bool。

      3,對(duì)象IsSpinningProperty注冊(cè)的類是聲明屬性IsSpinning的類,即,在其他類里,將看不到該依賴對(duì)象。

      現(xiàn)在,我們做最后的操作,修改屬性,將依賴對(duì)象IsSpinningProperty與屬性IsSpinning綁定。

      如何綁定呢?很簡(jiǎn)單,將我們屬性定義里的【private bool
      _IsSpinning】替換為我們剛剛定義的依賴【IsSpinningProperty】即可。
      public bool IsSpinning { get { return (bool)GetValue(IsSpinningProperty); }
      set { SetValue(IsSpinningProperty, value); } }
      這里我們看到了,在給屬性賦值和取值時(shí),用到了GetValue和SetValue,他們倆是哪來的呢?

      使用F12,我們跟蹤進(jìn)去,發(fā)現(xiàn)它們是類DependencyProperty里定義的方法,那么為什么我們?cè)诖绑w里也可以用呢?


      很簡(jiǎn)單,我們跟進(jìn)一下Window的父類,發(fā)現(xiàn)最后的父類Visual繼承了DependencyProperty,所以我們可以直接使用GetValue和SetValue來賦值和獲取依賴對(duì)象的值。也就是只要是繼承了類DependencyProperty的子類,都可以使用依賴屬性。

      完整版依賴屬性定義代碼:
      public static readonly DependencyProperty IsSpinningProperty =
      DependencyProperty.Register("IsSpinning", typeof(bool),
      typeof(DependecyUserControl)); public bool IsSpinning { get { return
      (bool)GetValue(IsSpinningProperty); } set { SetValue(IsSpinningProperty,
      value); } }
      到這里,依賴屬性的拆分就完事了,現(xiàn)在,大家應(yīng)該很清楚依賴屬性到底是什么了吧。
      現(xiàn)在你已經(jīng)理解這些依賴屬性的概念了,只要熟練一點(diǎn)點(diǎn),實(shí)現(xiàn)手敲依賴屬性已經(jīng)不是夢(mèng)了。?
      PS:有沒有人曾經(jīng)告訴你,依賴屬性的命名必須是 屬性名+Property,然后你還信以為真了。哈哈。

      依賴屬性的簡(jiǎn)單應(yīng)用

      現(xiàn)在讓我們來自定義一個(gè)帶依賴屬性的系統(tǒng)控件來加深記憶。
      public class KButton : Button { public static readonly DependencyProperty
      ForeImageProperty; public static readonly DependencyProperty BackImageProperty;
      public static readonly DependencyProperty MouseOverBackColorProperty; public
      static readonly DependencyProperty StretchProperty; static KButton() {
      ForeImageProperty = DependencyProperty.Register("ForeImage", typeof(string),
      typeof(KButton),null); ForeImageProperty =
      DependencyProperty.Register("BackImage", typeof(string), typeof(KButton),null);
      MouseOverBackColorProperty = DependencyProperty.Register("MouseOverBackColor",
      typeof(Brush), typeof(KButton), null); StretchProperty =
      DependencyProperty.Register("Stretch", typeof(Stretch), typeof(KButton), null);
      DefaultStyleKeyProperty.OverrideMetadata(typeof(KButton), new
      FrameworkPropertyMetadata(typeof(KButton)));//使KButton去讀取KButton類型的樣式,而不是去讀取Button的樣式
      } public string ForeImage { get { return (string)GetValue(ForeImageProperty); }
      set { SetValue(ForeImageProperty, value); } } public string BackImage { get {
      return (string)GetValue(BackImageProperty); } set { SetValue(BackImageProperty,
      value); } } public Brush MouseOverBackColor { get { return
      (Brush)GetValue(MouseOverBackColorProperty); } set {
      SetValue(MouseOverBackColorProperty, value); } } public Stretch Stretch { get {
      return (Stretch)GetValue(StretchProperty); } set { SetValue(StretchProperty,
      value); } } }
      如上述代碼所示,我們定義了一個(gè)繼承至Button的類KButton。

      在KButtion中,我們定義了四個(gè)依賴屬性:

      ForeImageProperty:按鈕的前景圖片。

      BackImageProperty:按鈕的背景圖片。

      MouseOverBackColorProperty:按鈕在鼠標(biāo)經(jīng)過時(shí)的顏色。

      StretchProperty:按鈕圖片的拉伸模式。

      代碼非常簡(jiǎn)潔,除了四個(gè)依賴屬性之外,什么也沒有;現(xiàn)在我們?nèi)ザxKbutton類型的樣式。

      為了演示方便,我直接將樣式定義在了App.xaml文件內(nèi)。
      <Style TargetType="{x:Type local:KButton}"> <Setter Property="Template">
      <Setter.Value> <ControlTemplate> <DockPanel Name="dpCon" Width="{Binding Width,
      RelativeSource={x:Static RelativeSource.TemplatedParent}}" Height="{Binding
      Height, RelativeSource={x:Static RelativeSource.TemplatedParent}}"
      Background="{Binding Background, RelativeSource={x:Static
      RelativeSource.TemplatedParent}}" ToolTip="{Binding ToolTip,
      RelativeSource={x:Static RelativeSource.TemplatedParent}}" > <DockPanel
      DockPanel.Dock="Top" Name="dpBtn"> <DockPanel.Background> <ImageBrush
      ImageSource="{Binding ForeImage, RelativeSource={x:Static
      RelativeSource.TemplatedParent}}" Stretch="{Binding
      Stretch,RelativeSource={x:Static RelativeSource.TemplatedParent}}"/>
      </DockPanel.Background> <TextBlock FontSize="15" VerticalAlignment="Center"
      HorizontalAlignment="Center" Foreground="#f9fcff" Text="{Binding Content,
      RelativeSource={x:Static RelativeSource.TemplatedParent}}"></TextBlock>
      </DockPanel> </DockPanel> <ControlTemplate.Triggers> <DataTrigger
      Binding="{Binding IsMouseOver,RelativeSource={x:Static RelativeSource.Self}}"
      Value="True"> <Setter Property="Background" TargetName="dpBtn"> <Setter.Value>
      <ImageBrush ImageSource="{Binding BackImage, RelativeSource={x:Static
      RelativeSource.TemplatedParent}}" Stretch="{Binding
      Stretch,RelativeSource={x:Static RelativeSource.TemplatedParent}}"/>
      </Setter.Value> </Setter> <Setter Property="Background" TargetName="dpCon"
      Value="{Binding MouseOverBackColor, RelativeSource={x:Static
      RelativeSource.TemplatedParent}}"></Setter> </DataTrigger> <DataTrigger
      Binding="{Binding BackImage,RelativeSource={x:Static
      RelativeSource.Self},Mode=TwoWay}" Value="{x:Null}"> <Setter
      Property="Background" TargetName="dpBtn"> <Setter.Value> <ImageBrush
      ImageSource="{Binding ForeImage, RelativeSource={x:Static
      RelativeSource.TemplatedParent}}" Stretch="{Binding
      Stretch,RelativeSource={x:Static RelativeSource.TemplatedParent}}"/>
      </Setter.Value> </Setter> </DataTrigger> <Trigger Property="IsEnabled"
      Value="true"/> <Trigger Property="IsEnabled" Value="false"> <Setter
      Property="Foreground" Value="Gray"/> </Trigger> </ControlTemplate.Triggers>
      </ControlTemplate> </Setter.Value> </Setter> </Style>
      樣式代碼如上所示,也非常簡(jiǎn)單,就是定義了一個(gè)模板,然后在模板里擺放好按鈕背景圖和按鈕文字的位置。然后將我們之前定義好的依賴屬性綁定到對(duì)應(yīng)的值上。

      其中需要注意的是,在模板中綁定自定義依賴屬性,是使用RelativeSource.TemplatedParent的,如{Binding ForeImage,
      RelativeSource={x:Static RelativeSource.TemplatedParent}}。

      而在模板的數(shù)據(jù)事件DataTrigger中,綁定依賴屬性的模式卻是分兩種的。

      第一種,綁定數(shù)據(jù)事件DataTrigger的條件時(shí),使用RelativeSource.Self,如{Binding
      IsMouseOver,RelativeSource={x:Static RelativeSource.Self}}。

      第二種,條件成立,觸發(fā)模板變化時(shí),使用RelativeSource.TemplatedParent,如{Binding BackImage,
      RelativeSource={x:Static RelativeSource.TemplatedParent}}。


      ----------------------------------------------------------------------------------------------------

      現(xiàn)在我們使用下我們制作好的自定義控件,代碼如下所示:
      <DockPanel> <StackPanel> <local:KButton Height="50" Width="50" Stretch="None"
      ForeImage="/Image/關(guān)閉.png" BackImage="/Image/關(guān)閉退出.png" Background="Gray"
      MouseOverBackColor="Brown"/> <local:KButton Height="50" Width="50"
      Margin="0,10,0,0" Stretch="None" ForeImage="/Image/關(guān)閉.png" Background="Gray"
      MouseOverBackColor="Brown"/> <local:KButton Height="100" Width="100"
      Margin="0,10,0,0" Content="籃子" Stretch="Fill" ForeImage="/Image/籃子.png"
      Background="Gray" MouseOverBackColor="Brown"/> </StackPanel> </DockPanel>
      界面效果如下:



      自定義用戶控件中使用依賴屬性

      首先我們添加新項(xiàng),然后選擇用戶控件。



      然后,我們添加一個(gè)依賴屬性HeaderTitle,同時(shí)設(shè)置當(dāng)前控件的DataContext為自身—this.DataContext = this。
      public string HeaderTitle { get { return
      (string)GetValue(HeaderTitleProperty); } set { SetValue(HeaderTitleProperty,
      value); } } public static readonly DependencyProperty HeaderTitleProperty =
      DependencyProperty.Register("HeaderTitle", typeof(string),
      typeof(DependecyUserControl), null); public DependecyUserControl() {
      this.DataContext = this; InitializeComponent(); }
      現(xiàn)在,我們?cè)谟脩艨丶腦aml頁面添加一個(gè)TextBlock,并綁定他的Text為我們剛剛定義的HeaderTitle,代碼如下所示。
      <Grid> <TextBlock Text = "{Binding HeaderTitle}"
      TextAlignment="Center"></TextBlock> </Grid>
      接著我們回到主窗體,引用這個(gè)用戶控件,代碼如下所示:
      <local:DependecyUserControl Height = "30" HeaderTitle="我是Header"
      DockPanel.Dock="Top"></local:DependecyUserControl>
      運(yùn)行結(jié)果:




      可以看到,我們成功在主頁面設(shè)置了用戶控件的依賴屬性,并讓他成功的綁定到了用戶控件中的TextBlock的Text屬性。也就是說,我們簡(jiǎn)單的實(shí)現(xiàn)了Header的Title動(dòng)態(tài)設(shè)置。

      結(jié)語

      WPF擁有非常強(qiáng)大的自定義能力,而,正確的學(xué)會(huì)了依賴屬性是體會(huì)到它強(qiáng)大的第一步。


      ----------------------------------------------------------------------------------------------------

      到此WPF依賴屬性的正確學(xué)習(xí)方法就已經(jīng)講解完成了。

      代碼已經(jīng)傳到Github上了,歡迎大家下載。

      Github地址:https://github.com/kiba518/WpfDependency
      <https://github.com/kiba518/WpfDependency>


      ----------------------------------------------------------------------------------------------------

      注:此文章為原創(chuàng),任何形式的轉(zhuǎn)載都請(qǐng)聯(lián)系作者獲得授權(quán)并注明出處!
      若您覺得這篇文章還不錯(cuò),請(qǐng)點(diǎn)擊下方的【推薦】,非常感謝!

      https://www.cnblogs.com/kiba/p/11149147.html
      <https://www.cnblogs.com/kiba/p/11149147.html>

      友情鏈接
      ioDraw流程圖
      API參考文檔
      OK工具箱
      云服務(wù)器優(yōu)惠
      阿里云優(yōu)惠券
      騰訊云優(yōu)惠券
      京東云優(yōu)惠券
      站點(diǎn)信息
      問題反饋
      郵箱:[email protected]
      QQ群:637538335
      關(guān)注微信

        <ul id="qxxfc"><fieldset id="qxxfc"><tr id="qxxfc"></tr></fieldset></ul>
          奇米麻豆 | 逼逼视频 | 亚洲精品免费视频 | 国产精品久久久久久久久久久久久久 | 久久婷婷网 | 精东AV | 美女被操网站免费 | 欧美色图1| 孙头退休后日女儿的幸福生活 | 无码影视在线观看 |