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

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

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

      WPF依賴屬性學習

      概述

      WPF 依賴屬性(Dependency Property)是 WPF 框架的核心基礎設施之一,它擴展了傳統 .NET 屬性的能力,為 WPF 提供數據綁定、動畫、樣式、繼承值、屬性值變更通知等高級功能。

      為什么需要設計依賴屬性?

      因為依賴屬性做到了CLR屬性沒做到的一些事情。

      列舉幾個場景:

      1、數據驅動 UI 的動態性需要“可計算的值

      在 WPF 里,綁定的值、樣式 Setter 的值、觸發器的值、動畫幀的值,都是事后才知道的,甚至可以在運行時不斷切換來源。

      CLR 屬性:值寫死在一個私有字段里,誰最后 set 就留誰。

      依賴屬性:屬性系統先查看“當前這一幀到底是誰最有發言權”,再給出最終值——也就是“值是從外部來的,我只是按優先級算一算”的依賴計算。

      2、大規模對象樹的內存壓力要求“默認值共享

      WPF 的控件樹隨隨便便成千上萬實例,如果每個 Button 都把 FontSize = 11 存一份 double,內存就爆炸了。

      依賴屬性把“默認值”壓縮到一個靜態全局哈希表里,沒顯式設置的實例,直接查表用同一份值。

      3、樣式 / 動畫 / 綁定 / 繼承 / 觸發器 / 資源多路輸入需要統一的“優先級規則

      同一個 Background,可以是:本地值(紅),主題樣式(藍),動畫(綠),觸發器(黃)……

      傳統屬性里誰最后 set 誰贏,根本無法表達這種“多源頭分時復用”的復雜策略。
      依賴屬性為此內置了一套顯式的優先級表(動畫>本地值>觸發器>樣式…),系統每次重新評估就行,無需控件開發者自己寫狀態機。

      4、跨父子樹的“屬性值繼承

      典型例子:FontSize 設到 Window 上,所有子孫 TextBlock 直接復用該值,但中途隨時可以用樣式或本地值覆蓋。

      傳統字段存儲實現:父級改一次就要遞歸遍歷整棵樹;

      依賴屬性:子元素在取值時惰性向上詢問,邏輯/性能都優雅。

      學習依賴屬性

      在創建自定義的時候,創建一個依賴屬性的示例如下所示:

        public int Value
        {
            get => (int)GetValue(ValueProperty);
            set => SetValue(ValueProperty, value);
        }
        public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
            nameof(Value), typeof(int), typeof(RatingControl),
            new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnValueChanged, CoerceValue));
      

      首先來看看命名,一個CLR屬性是Value,依賴屬性是ValueProperty,這是一種命名約定,可以很容易將這兩個東西關聯起來。

      依賴屬性都是通過DependencyProperty.Register方法注冊:

      public static readonly DependencyProperty ValueProperty =
      DependencyProperty.Register(
          nameof(Value),          // 屬性名 Value
          typeof(int),            // 屬性類型
          typeof(RatingControl),  // 所屬類型
          new FrameworkPropertyMetadata(
              0,                                   // 默認值
              FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, // 默認為雙向綁定
              OnValueChanged,                      // 值發生變更時的回調
              CoerceValue)                         // 強制值回調
      );
      

      CoerceValue是強制回調:

      private static object CoerceValue(DependencyObject d, object baseValue)
      {
        var ctl = (RatingControl)d;
        int v = Math.Max(0, (int)baseValue); // 下限
        v = Math.Min(v, ctl.Max);            // 上限
        return v;
      }
      

      OnValueChanged是變更回調:

      private static void OnValueChanged(
        DependencyObject d, DependencyPropertyChangedEventArgs e)
      {
        var ctl = (RatingControl)d;
        ctl.UpdateVisualStates();
      }
      

      作用:值真正改變后通知控件更新 UI。

      e 中包含舊值 e.OldValue 與新值 e.NewValue,可進一步比較差異。

      生命周期小結(一個賦值的全過程)

      代碼 / 綁定 / 動畫嘗試改變 Value。

      WPF 調用 CoerceValue 讓控件有機會矯正值。

      如果矯正后的值與當前存儲值相同,流程結束;否則進入下一步。

      觸發 OnValueChanged → 更新UI。

      因為是 BindsTwoWayByDefault,若存在綁定的源(ViewModel),其對應屬性也會被同步。

      現在大概了解了依賴屬性的設計,你可能也聽說過“附加屬性”與“繼承屬性”。

      其實官方并沒有“繼承屬性”這個稱謂,繼承屬性只是將依賴屬性設置成可繼承罷了。

      要想更好地理解依賴屬性的概念,一個很好的方式就是去看WPF的源碼,看看在源碼中是如何使用的,現在就讓我們一起去源碼中找找看吧!!

      先來看看普通的依賴屬性定義:

      目前我們接觸到了DependencyPropertyDependencyPropertyKey

      DependencyPropertyKey表示只讀依賴屬性。

      這里官方源碼將按鈕是否按下這個屬性設置為了只讀依賴屬性,為什么官方是這樣做的呢?

      想象一下一個按鈕的 IsPressed 屬性。這個屬性應該是 true 還是 false,不應該由應用程序的邏輯直接決定(比如,你不應該寫 myButton.IsPressed = true; 來“按下”一個按鈕)。它的狀態應該完全由用戶的交互行為(鼠標按下、觸摸、鍵盤空格鍵等)來驅動。

      如果你把它做成一個普通的可以隨意讀寫的屬性:

      public bool IsPressed { get; set; }
      

      那么任何代碼都可以修改它,這會破壞按鈕的內在邏輯和行為一致性。

      如果你把它做成一個普通的只讀屬性:

      private bool _isPressed;
      public bool IsPressed { get { return _isPressed; } }
      

      雖然外部代碼不能修改了,但這樣做有幾個缺點:

      不支持 WPF 高級功能:它不再是一個依賴屬性,因此無法享受數據綁定、樣式、動畫、屬性值繼承等 WPF 的核心特性。比如,你無法在 XAML 中寫一個 Trigger 來在 IsPressed 為 true 時改變按鈕的背景色。

      缺少變更通知:如果 _isPressed 的值改變了,WPF 的其他部分(比如 UI 渲染系統)不會自動知道。你需要手動實現 INotifyPropertyChanged 接口,這額外增加了復雜性。

      為了解決上述問題,WPF 引入了“只讀依賴屬性” (Read-Only Dependency Property) 。這種屬性擁有兩全其美的優勢:

      對外是只讀的:保護了屬性的完整性,防止外部代碼隨意篡改。

      內部是可讀寫的:屬性的“所有者”可以在特定邏輯下修改其值。

      擁有依賴屬性的全部特性:支持數據綁定、樣式、動畫、觸發器等。

      再來看看附加依賴屬性:

      Grid.Row是一個很經典的附加依賴屬性。

      注冊附加依賴屬性使用的是DependencyProperty.RegisterAttached方法。

      附加屬性必須提供靜態的GetSet 方法:

      在WPF中一個很經典的可繼承依賴屬性的例子就是FontSize,讓我們來看看它的定義:

      使用了FrameworkPropertyMetadataOptions.Inherits

      這個枚舉類有以下幾個選項:

      名稱 說明
      None 無標志。
      AffectsMeasure 此屬性影響測量(Measure)過程。當此屬性值改變時,元素需要重新計算其所需大小。
      AffectsArrange 此屬性影響布局(Arrange)過程。當此屬性值改變時,元素需要重新定位并確定其最終大小。
      AffectsParentMeasure 此屬性影響父級的測量過程。當此屬性值改變時,其父元素需要重新進行測量。
      AffectsParentArrange 此屬性影響父級的布局過程。當此屬性值改變時,其父元素需要重新進行布局。
      AffectsRender 此屬性影響渲染。當此屬性值改變時,元素可能需要部分或完全重繪。
      Inherits 此屬性的值可以被子元素繼承。
      OverridesInheritanceBehavior 此屬性會導致繼承和資源查找過程,忽略在查找路徑上任何元素 (FE) 設置的 InheritanceBehavior 值。
      NotDataBindable 此屬性不支持數據綁定。
      BindsTwoWayByDefault 對此屬性的數據綁定默認為雙向(Two-Way)模式。
      Journal 在通過 URI 進行日志記錄/導航時,此屬性的值應該被保存和恢復。
      SubPropertiesDoNotAffectRender 此屬性的子屬性不會影響渲染。例如,若屬性 X 有子屬性 Y,則修改 X.Y 不會觸發渲染更新。

      現在只是差不多了解了WPF中的依賴屬性的一些概念與使用,要想真正明白依賴屬性的設計與實現,還得多研究研究源碼。

      posted @ 2025-09-04 18:14  mingupupup  閱讀(591)  評論(5)    收藏  舉報
      主站蜘蛛池模板: 色就色中文字幕在线视频| 国产精品熟女亚洲av麻豆| 免费观看一级欧美大| 无码av中文一区二区三区桃花岛 | 成人免费无遮挡在线播放| 日韩人妻少妇一区二区三区| 在线播放深夜精品三级| 茂名市| 丰满人妻熟妇乱又仑精品| 久久天天躁狠狠躁夜夜婷| 26uuu另类亚洲欧美日本| 国产精品一区二区三区av| 国产精品国产三级国快看| 国产乱码日产乱码精品精| 99久久久国产精品免费无卡顿| 人妻体内射精一区二区三区| 国产偷国产偷亚洲高清午夜| 亚洲精品国产一二三区| 2020年最新国产精品正在播放| 亚洲高潮喷水无码AV电影| 中文字幕V亚洲日本在线电影| 国产成人av乱码在线观看| 国产精品无码成人午夜电影| 中国熟女仑乱hd| 国产成人精品久久一区二| 狠狠cao日日穞夜夜穞av| 体态丰腴的微胖熟女的特征| 亚洲综合精品第一页| 在线精品自拍亚洲第一区| 亚欧洲乱码视频在线专区| 国产不卡在线一区二区| 久久久久无码精品亚洲日韩| 国产成年码av片在线观看| 国产精品一线二线三线区| 亚洲AV无码秘?蜜桃蘑菇| 青青草无码免费一二三区| 日本熟妇XXXX潮喷视频| 亚洲香蕉av一区二区蜜桃| 99在线精品免费视频九九视| 国产一区二区av天堂热| 鲁一鲁一鲁一鲁一澡|