<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      WPF - 屬性系統(tǒng) - APaas(AttachedProperty as a service)

        是的,文章的題目看起來很牛,我承認。

        附加屬性是WPF中的一個非常重要的功能。例如在設(shè)置布局的過程中,軟件開發(fā)人員就常常通過DockPanel的Dock附加屬性來設(shè)置其各個子元素所處的布局位置。同樣地,在為程序添加一個新的功能時,我們也常常需要創(chuàng)建自定義的附加屬性來完成該功能。

       

      附加屬性簡介

        首先,我們要對附加屬性有一個簡單的認識:什么是附加屬性,而為什么WPF提供了附加屬性呢?

        在WPF中,附加屬性用來表示定義在一個類型上,卻可以在其它特定類型實例上被使用的屬性。由于該屬性并非定義在這些實例所對應(yīng)的類型之上,而更像是為這些類型額外地添加了一系列值,因此其被稱為附加屬性。

        一種較好的理解附加屬性這種行為的方式則是將其當(dāng)作一個服務(wù)。其中子元素通過設(shè)置這些附加屬性的值來定義如何使用服務(wù)。而定義附加屬性的類型將根據(jù)這些子元素中設(shè)置的數(shù)值決定其所提供服務(wù)的方式,如一個控件應(yīng)該放置在哪里。這種使用方法也便是決定我們是否創(chuàng)建一個附加屬性的最重要因素。

        而實現(xiàn)一個附加項屬性則非常簡單。首先,軟件開發(fā)人員需要通過調(diào)用DependencyProperty類的RegisterAttached()函數(shù)在屬性系統(tǒng)中聲明一個附加屬性。與依賴項屬性不同的是,由于其并非作用于定義該附加屬性的類型上,因此無法提供CLR屬性包裝,而是提供了以Get-以及Set-作為屬性名前綴的專用方法。這些專用方法中,軟件開發(fā)人員可以通過規(guī)定參數(shù)以及返回值的類型等方式限制使用該附加屬性的類型以及該屬性的值。

        現(xiàn)在就以.net源碼中的DockPanel.Dock附加屬性的實現(xiàn)來熟悉創(chuàng)建附加屬性的過程:

      public static readonly DependencyProperty DockProperty = DependencyProperty
          .RegisterAttached("Dock", typeof(Dock), typeof(DockPanel), 
          ……);
      
      public static Dock GetDock(UIElement element)
      {
          if (element == null)
          {
              throw new ArgumentNullException("element");
          }
          return (Dock) element.GetValue(DockProperty);
      }
      
      public static void SetDock(UIElement element, Dock dock)
      {
          if (element == null)
          {
              throw new ArgumentNullException("element");
          }
          element.SetValue(DockProperty, dock);
      }

        首先,軟件開發(fā)人員需要通過DependencyProperty類的RegisterAttached()以及RegisterAttachedReadonly()函數(shù)來向?qū)傩韵到y(tǒng)中注冊附加屬性。這兩個函數(shù)所使用的各個參數(shù)與Register()函數(shù)所使用的各個參數(shù)類似:通過參數(shù)name指定附加屬性的名稱;通過propertyType參數(shù)指定附加屬性的類型;通過ownerType參數(shù)指定附加屬性所在的類型;通過defaultMetadata參數(shù)指定附加屬性所使用的元數(shù)據(jù);最后通過validateValueCallback指定驗證邏輯。而在附加屬性的承載類型中,軟件開發(fā)人員需要通過一個靜態(tài)公有的DependencyProperty來記錄這些新注冊的附加屬性。這個附加屬性的屬性名需要遵守一定的規(guī)則:其需要由在調(diào)用RegisterAttached()函數(shù)時所傳入的參數(shù)name以及后綴-Property組合而成。接下來,軟件開發(fā)人員就需要定義用來訪問附加屬性的讀寫函數(shù)。這些函數(shù)的名稱則需要通過前綴Get-和Set-以及附加屬性注冊時所傳入的參數(shù)name共同組成。在這些函數(shù)內(nèi)部,軟件開發(fā)人員只需要調(diào)用DependencyObject的GetValue()和SetValue()即可。

        讓我們來回想一下WPF中DockPanel的使用過程:軟件開發(fā)人員首先在XAML中聲明了一個DockPanel,并在該其中聲明了眾多的子元素,以表示需要承載在該DockPanel中的界面組成。在這些界面組成的聲明中,我們可以使用DockPanel.Dock屬性來指定每個子元素需要放置在DockPanel的哪個位置。整個過程如下面代碼所示:

      <DockPanel LastChildFill="True">
          <Border DockPanel.Dock="Top" ...>
              <TextBlock Foreground="Black">Dock = "Top"</TextBlock>
          </Border>
          ...
      </DockPanel>

        在XAML編譯器遇到對DockPanel.Dock屬性的賦值時,其會將該賦值轉(zhuǎn)化為對DockPanel.SetDock()函數(shù)的調(diào)用。該函數(shù)會以包含DockPanel.Dock屬性賦值的界面元素以及被賦予的值作為參數(shù)。而在執(zhí)行布局計算的時候,DockPanel會使用GetDock()函數(shù)將所有子元素的DockPanel.Dock附加屬性值讀取出來,并根據(jù)這些值安排各個子元素所處的位置。這就相當(dāng)于DockPanel提供布局計算的服務(wù),而每個子元素則通過附加屬性DockPanel.Dock提供了自身所需要的服務(wù)的類型。

        另外需要強調(diào)的一點則是附加屬性的Get-和Set-函數(shù)中對能使用附加屬性的類型的限制。在DockPanel所提供的GetDock()和SetDock()函數(shù)中,第一個屬性的類型是UIElement,也就表示DockPanel只為UIElement提供附加屬性的服務(wù)。這其實也是附加屬性限制其所可施行類型的最常用方法:在Get-和Set-函數(shù)的定義中將第一個參數(shù)的類型設(shè)置為附加屬性的目標(biāo)類型,從而限制其它類型對該附加屬性的使用。

        同理,軟件開發(fā)人員也可以為Get-函數(shù)的返回值以及Set-函數(shù)的參數(shù)value指定一個特定的類型,以防止用戶代碼為附加屬性設(shè)置一個其它類型的值。其內(nèi)部實現(xiàn)會直接調(diào)用傳入的參數(shù)的GetValue()和SetValue()函數(shù)來完成附加屬性的設(shè)置。這兩個函數(shù)并沒有以自身實例作為參數(shù)。也就是說,附加屬性并沒有設(shè)置在聲明該附加屬性的類型實例上,而是設(shè)置在了使用附加屬性的實例上。

        從上面的講解中可以看出,附加屬性所對應(yīng)的Get-和Set-函數(shù)內(nèi)部并沒有引用任何宿主類型成員,而是將屬性值設(shè)置到了傳入的參數(shù)上。因此在定義一個附加屬性的時候,依賴項屬性的宿主類型不必從DependencyObject類派生。

        如果需要讓附加屬性所對應(yīng)的服務(wù)能夠正確執(zhí)行,僅僅限制附加屬性的目標(biāo)類型是不夠的。附加屬性所提供的服務(wù)常常需要按照一定的方式搜索其所在類型之下的各個子元素,以搜集它們所包含的有關(guān)服務(wù)的信息,并根據(jù)這些信息提供服務(wù)。就以DockPanel類所提供的DockPanel.Dock附加屬性為例:

      protected override Size ArrangeOverride(Size arrangeSize)
      {
          UIElementCollection internalChildren = base.InternalChildren;
          int count = internalChildren.Count;
          for (int i = 0; i < count; i++)
          {
              UIElement element = internalChildren[i];
              if (element != null)
              {
                  Size desiredSize = element.DesiredSize;
                  Rect finalRect = … // 子元素最終所處的布局位置
                  switch (GetDock(element))
                  {
                      case Dock.Left:
                          x += desiredSize.Width;
                          finalRect.Width = desiredSize.Width;
                          break;
      
                      case Dock.Top: // 依次處理Dock.Top,Dock.Right以及Dock.Bottom等情況
                  }
                  element.Arrange(finalRect);
              }
          }
          return arrangeSize;
      }

        上面的示例代碼非常好地展示了一個附加屬性是如何在類型中被使用的:在通常情況下,包含附加屬性的類型常常包含了一個集合,以記錄其所包含的各個子元素。在特定邏輯運行過程中,該集合內(nèi)所記錄的所有子元素將被遍歷。在每次遍歷中,執(zhí)行邏輯都會取得子元素的附加屬性值,并以此屬性值來決定子元素的具體行為。

        因此,如果這些信息并沒有按照正確的方式提供,那么附加屬性所提供的服務(wù)也可能不被正確運行。就以下面的代碼為例:

      <DockPanel LastChildFill="True">
          <Border DockPanel.Dock="Top" ...>
              <TextBlock DockPanel.Dock=”Bottom” Foreground="Black">Dock = "Top"</TextBlock>
          </Border>
          ...
      </DockPanel>

        在上面的代碼中,DockPanel的Border類型的子元素以及Border所包含的TextBlock元素都設(shè)置了DockPanel.Dock附加屬性。但是由于DockPanel僅僅排列其所包含的各個子元素,而這些子元素所各自包含的內(nèi)嵌元素的布局則是由各個子元素自己決定,因此DockPanel僅僅對它的直接子元素的DockPanel.Dock附加屬性進行處理。所以在上面的例子中,TextBlock元素所設(shè)置的DockPanel.Dock附加屬性將不會被處理。

       

      附加屬性相關(guān)特性

        現(xiàn)在來想想附加屬性在XAML中的使用。在編寫XAML標(biāo)記的時候,Visual Studio會根據(jù)當(dāng)前輸入提示可用的各屬性。這其中就有附加屬性:

        但是這里就出現(xiàn)了問題:該列表中并沒有DockPanel.Dock附加屬性,卻只有Grid相關(guān)的附加屬性。這是為什么呢?查看有關(guān)附加屬性的實現(xiàn)時,我們發(fā)現(xiàn)了一些端倪:

      [AttachedPropertyBrowsableForChildren]
      public static int GetColumn(UIElement element)
      {
          if (element == null)
          {
              throw new ArgumentNullException("element");
          }
          return (int) element.GetValue(ColumnProperty);
      }

        在上面的代碼中,我們可以看到Column附加屬性的Get-訪問函數(shù)上添加了一個特性AttachedPropertyBrowsableForChildren。查看MSDN可以知道,該屬性用來標(biāo)示當(dāng)前附加屬性可以在邏輯樹中的子元素中被使用。其包含兩種不同的子元素查詢方法:在沒有顯式地將IncludeDescendants屬性標(biāo)為true的時候,依賴項屬性將僅僅在子元素中可見。而在將IncludeDescendants屬性標(biāo)為true的時候,該依賴項屬性可以在相應(yīng)元素中的任何子元素中出現(xiàn)。一般情況下,該特性只在Get-訪問符上施行。

        在定義一個附加屬性的時候,我們的確可以通過標(biāo)示這些特性使得一個附加屬性可以在一個元素的屬性列表中出現(xiàn)。但是該附加屬性的設(shè)置是否被處理則是由附加屬性的實際執(zhí)行邏輯所決定的。因此軟件開發(fā)人員在使用該特性使一個附加屬性在某個元素中出現(xiàn)的時候,您首先需要盡量保證處理邏輯能處理該特性所標(biāo)示的附加屬性可見范圍。

        另一個較為有用的特性就是AttachedPropertyBrowsableForType。該特性允許軟件開發(fā)人員指定一個附加屬性只對特定類型可見。在需要令附加屬性對多種類型可見的時候,軟件開發(fā)人員需要在附加屬性的Get-訪問符上添加多個該類型的特性。

        而最后一個特性就是AttachedPropertyBrowsableWhenAttributePresentAttribute。該特性表示只有宿主類型上標(biāo)明了特定特性時,該依賴項屬性才可見。這并不是一個非常常用的特性,因此我們將不在這里對其進行講解。

       

      附加屬性的綁定

        從上面的講解中您已經(jīng)了解到,附加屬性實際上就是一個依賴項屬性,因此其同樣可以作為綁定的數(shù)據(jù)源使用。但是此時綁定所使用的標(biāo)記則與普通的依賴項屬性有所不同。例如在需要綁定到靜態(tài)實例local:StaticClass的Button屬性所設(shè)置的Grid.Row附加屬性的時候,軟件開發(fā)人員需要使用圓括號將附加屬性括起:

      {Binding Source={x:Static local:StaticClass}, Path=Button.(Grid.Row)}

        使用不同標(biāo)記的原因則非常簡單:XAML解析器需要根據(jù)不同的標(biāo)記來判斷綁定表達式中的各個組成到底是對依賴項屬性還是附加屬性的引用。

        轉(zhuǎn)載請注明原文地址:http://www.rzrgm.cn/loveis715/p/4343381.html

        商業(yè)轉(zhuǎn)載請事先與我聯(lián)系:silverfox715@sina.com,我只會要求添加作者名稱以及博客首頁鏈接。

      posted @ 2015-03-20 20:40  loveis715  閱讀(2195)  評論(1)    收藏  舉報
      主站蜘蛛池模板: 沙洋县| 欧美精品亚洲精品日韩专| 亚洲经典av一区二区| 人人妻人人澡人人爽人人精品电影| 国产一区二区三区18禁| 国产系列丝袜熟女精品视频| 亚洲国产成人久久77| 国产成a人亚洲精v品无码性色| 国产午夜福利不卡在线观看| 亚洲中文字幕日韩精品| 强奷乱码欧妇女中文字幕熟女| 东京热人妻丝袜无码AV一二三区观| 免费无码一区无码东京热| 色综合网天天综合色中文| 亚洲欧美一区二区三区图片| 国产视频有码字幕一区二区| 精品人妻午夜一区二区三区四区| 色综合色综合久久综合频道 | 内射视频福利在线观看| 在线aⅴ亚洲中文字幕| 骚虎三级在线免费播放| 欧美一本大道香蕉综合视频| 乱码中字在线观看一二区| 天天澡天天揉揉av无码| 国产一区二区午夜福利久久| 成人免费视频一区二区三区| 国内极度色诱视频网站| 国产精品亚洲二区在线播放| 亚洲午夜精品国产电影在线观看| 久久精品第九区免费观看| 色播久久人人爽人人爽人人片av | 中文有码字幕日本第一页| a级黑人大硬长爽猛出猛进| 亚洲成人av在线资源| 色综合久久夜色精品国产| 日本精品极品视频在线| 麻豆一区二区中文字幕| 新野县| 亚洲精品国产一二三区| 武隆县| 宣威市|