1. 程式人生 > >WPF 依賴屬性的建立與使用

WPF 依賴屬性的建立與使用

 WPF 中最大的亮點當屬 Binding 了,.NET 給我們提供了足夠多的屬性來讓我們非常方便地進行資料繫結等操作。但即使如此,依然會有想編寫自己的屬性來進行 Binding 等操作。

在 WPF 中,微軟將屬性的概念延伸了一下,推出了“依賴屬性”這個概念。所謂依賴屬性,就是自己本身沒有值而值是依賴別人的值。

 為什麼要使用依賴屬性呢?舉個例子,一個 TextBlock 有上百個屬性,但是基本上我們常用的就是 Text 屬性,當你在使用建構函式建立這個 TextBlock 的時候,這個例項的控制元件就已經被定下來了,隨之而來的是大量不必要的空間浪費。而依賴屬性,依賴別人的值而設定自己的值,這節省了大量不必要的空間浪費,而且可以方便的進行資料繫結,所以我們才要用依賴屬性。

如何建立一個依賴屬性呢?程式碼如下:

public static readonly DependencyProperty ContentProperty = DependencyProperty.Register("Content", typeof(string), typeof(Test));

首先依賴屬性的訪問許可權可以是 public 或者 private 和 protected,但是如果是 private 或者 protected 的話,要想讓外界訪問,就需要給這個依賴屬性新增一個 public 的屬性訪問器以暴露這個依賴屬性,稍後會介紹如何給該依賴屬性繫結一個 CLR 屬性,當然你也可以自己寫一個 CLR 屬性來封裝該依賴屬性的值,但這樣做會影響我們使用 Binding 等功能。

而 static 和 readonly 是必須的,所以即使你建立了一百個依賴物件,也僅佔一個空間,當然這可能有點難以理解,靜態的和只讀的與我們正常使用依賴屬性的情況完全不符,不過你可以暫時或略這裡,這樣寫的原因不是本文想要講的,我會在之後的部落格裡講為什麼這樣寫。

然後是 DependencyProperty ,這是依賴屬性類,所以後面的 ContentProperty 就是這個物件了。這裡有一個命名規則,就是依賴屬性的物件名都已  Peoperty 結尾,這樣就表明他是一個依賴屬性,方便他人閱讀和理解。

你會發現我們並不是用建構函式來建立依賴屬性的,而是使用了 DependencyProperty 類中的一個靜態方法,來建立一個依賴屬性。該方法有多個過載,詳細請參見 MSDN 文件,這裡使用的是最簡單的過載,有三個引數:第一個是一個 String 物件,值為給這個依賴屬性繫結的 CLR 屬性;第二個為 Type 型別,表明這個依賴屬性儲存的值是什麼型別,注意是這個依賴屬性儲存的值,這個依賴屬性的型別永遠是 DependencyProperty ;第三個引數也是 Type 型別,表明擁有該依賴屬性的類是哪一個,也可以說把這個依賴屬性註冊到哪個類裡,所以用 Register 這個名字就顯得合理了。

下面來看一個稍完整的示例:

首先建立一個 WPF 專案,並建立一個類,名為 Test 。MainWindow.xaml 中程式碼如下:

<Window x:Class="wpfblog.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <TextBox x:Name="textBox" Grid.Row="0"></TextBox>
        <Button x:Name="button" Click="button_Click" Grid.Row="1">點選顯示 Content</Button>
    </Grid>
</Window>

Test.cs 檔案中的程式碼如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;

namespace Blog_DependencyProperty
{
    public class Test : DependencyObject
    {
        public static readonly DependencyProperty ContentProperty = DependencyProperty.Register("Content", typeof(string), typeof(Test));
        
        public Test()
        {
            
        }
    }
}
從 Test.cs 的程式碼中可以看到,建立依賴屬性首先要讓當前類繼承 DependencyObject 類,在這裡,一個物件名為 ContentProperty 的依賴屬性就建立完成了。

如何為其新增 Binding 呢?MainWindow.xaml.cs 程式碼如下 :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace Blog_DependencyProperty
{
    /// <summary>
    /// MainWindow.xaml 的互動邏輯
    /// </summary>
    public partial class MainWindow : Window
    {
        Test test;

        public MainWindow()
        {
            InitializeComponent();
            test = new Test();
            Binding binding = new Binding("Text") { Source = textBox };
            BindingOperations.SetBinding(test, Test.ContentProperty, binding);
        }

        private void button_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show((string)test.GetValue(Test.ContentProperty));
        }
    }
}

重點在建構函式裡,其中第一行程式碼不必說了,第二行建立了一個 Test 例項,第三行則是新增繫結,資料來源是在 XAML 檔案中建立的 TextBox 物件,Path 是 Text 屬性(這個Text 屬性其實是一個 CLR 屬性,真正的依賴屬性其實是 TextProperty),這裡就不再贅述 Path 等概念了;第四行程式碼是給資料來源和資料目標之間新增繫結,如果你使用 test.SetBinding 方法,你會發現微軟沒有在 DependencyObject 類中提供這個方法,所以你需要使用如第四行所示的程式碼來建立一個繫結,資料目標是 test 物件,依賴屬性是 ContentProperty ,第三個引數就是之前例項化的 binding 了。其實你應該覺得奇怪,資料目標是 test 物件,一般來說應該是以後臺程式碼為資料來源,前臺 UI 控制元件為資料目標,這裡反了過來,且 test 物件沒有 SetBinding 方法,需要使用 BindingOperations 類中的靜態方法,這也表達了微軟希望 UI 控制元件作為資料目標,實現資料驅動 UI 的思想(讀者也可以從類的層級方面發現問題)。

而後面給按鈕新增的事件處理函式很好理解。利用從 DependencyObject 物件繼承而來的 GetValue 和 SetValue 方法可以讀取或設定依賴屬性的值。注意 GetValue 的方法返回值是 object 型別,所以你需要手動轉換為你需要的型別。SetValue 方法稍後再講。

好了,執行一下程式,在 TextBox 中輸入內容,點選按鈕,就會顯示出你輸入的內容。


內容就請大家忽略吧,最近博主有點感情受挫。

好了,言歸正傳,你會發現這裡並沒有用到建立(或者說註冊更合適)依賴屬性時的第一個引數,是的,即使沒有 CLR 屬性,也一樣可以完美執行。

那麼為什麼我們還要有 CLR 屬性來封裝這個依賴屬性的值呢?讀者可以試下:

textBox.Text = Test.ContentProperty;
textBox.Text = (string)Test.ContentProperty;

這兩行程式碼都會報錯,因為無法將一個 DependencyProperty 型別的物件轉換為 string ,當然有無法轉為其他一些型別,而我們要想使其作為資料來源的 Path 的話(之前是資料目標),就必須要得到它的值,你無法將一個函式用作 Path 吧,所以我們需要一個 CLR 屬性。當然,使用 CLR 屬性也更符合面向物件設計的一些思想,我們使用也更加方便。

新增如下程式碼:

public string Content
{
    get
    {
        return (string)GetValue(ContentProperty);  
    }

    set
    {
        SetValue(ContentProperty, value);
    }
}
這段程式碼想必大家都很熟悉了,SetValue 的用法大家也一目瞭然,這裡我們想演示如何使自己建立的依賴屬性作為資料來源,所以我們將之前的按鈕改為一個 TextBlock ,並設定其 x:name 值為 textBlock 。

在 MainWindow.xaml.cs 中,刪掉按鈕的那個事件處理函式,然後在建構函式中新增如下程式碼:

textBlock.SetBinding(TextBlock.TextProperty, new Binding("Content") { Source = test });

好了,來讓我們執行下吧。什麼?等等?還沒實現 Inotifypropertychanged 介面?不管怎麼樣,先讓我們執行看看吧。


沒錯,像這樣建立的依賴屬性可以直接作為資料來源使用。上面這個例子已經證明了現在我們自己建立的這個依賴屬性既可以作為資料目標也可以作為資料來源。

好了,本篇部落格就講到這裡,謝謝大家!歡迎大家批評指正。

Remember !You Make Luck !

相關推薦

WPF 依賴屬性建立使用

 WPF 中最大的亮點當屬 Binding 了,.NET 給我們提供了足夠多的屬性來讓我們非常方便地進行資料繫結等操作。但即使如此,依然會有想編寫自己的屬性來進行 Binding 等操作。 在 WPF 中,微軟將屬性的概念延伸了一下,推出了“依賴屬性”這個概念。所謂依賴屬

WPF依賴屬性(續)(2)依賴屬性附加屬性的區別

原文: WPF依賴屬性(續)(2)依賴屬性與附加屬性的區別        接上篇,感謝各位的評論,都是認為依賴屬性的設計並不是為了節省記憶體,從大的方面而講是如此.樣式,資料繫結,動畫樣樣都離不開它.這篇我們來看下依賴屬性與附加屬性的區別. 註冊方法

WPF 依賴屬性概念

img 邏輯 數據綁定 .com 開發人員 component alt 交互 splay 理解依賴屬性   在 WPF 中變成相比較於 傳統 Windows Forms 變成發生了較大的改變. 屬性現在以一組服務的形式提供給開發人員. 這組服務就叫做屬性系統.   由 WP

[CodeSmith] WPF依賴屬性腳本

text bject setvalue classname csharp gist fault smi arp <%-- Name: WPF 依賴屬性 Author: Dxq Description: 生成WPF的依賴屬性 --%>

WPF 依賴屬性和附加屬性

text 依賴 通過 strong wpf hashtable 如果 hash nbsp 依賴屬性: 依賴屬性就是自己沒有值,通過Binding從數據源獲得值,就是依賴在別人身上,擁有依賴屬性的對象稱為依賴對象。 依賴屬性的值存在哪裏? 在WPF運行時,維護了一個全局的Ha

WPF依賴屬性詳解

property smo info 設置 size ont idm sde 讀者 WPF 依賴屬性 英文譯為 Dependency Properties,是WPF引入的一種新類型的屬性,在WPF中有著極為廣泛的應用,在WPF中對於WPF Dependency Propert

WPF依賴屬性(續)(1)

原文: WPF依賴屬性(續)(1)                 之前有寫過幾篇文章,詳細地介紹了依賴屬性的基本使用方法,如果你不想了解其內部實現機制的話,那麼通過那

WPF依賴屬性(續)(3)依賴屬性儲存

原文: WPF依賴屬性(續)(3)依賴屬性儲存          在之前的兩篇,很多朋友參與了討論,也說明各位對WPF/SL計數的熱情,對DP系統各抒已見,當然也出現了一些分歧. 以下簡稱DP為依賴屬性 總結下上文: 討論了D

WPF依賴屬性的正確學習方法

前言 我在學習WPF的早期,對依賴屬性理解一直都非常的不到位,其惡果就是,我每次在寫依賴屬性的時候,需要翻過去的程式碼來複制黏貼。 相信很多朋友有著和我相同的經歷,所以這篇文章希望能幫助到那些剛剛開始學依賴屬性的朋友。 那些[討厭]的依賴屬性的講解文章 初學者肯定會面臨一件事,就是百度,谷歌,或者MS

WPF: 只讀依賴屬性的介紹實踐

val 包括 結合 通過 觸發 clas 就是 post 能夠 在設計與開發 WPF 自定義控件時,我們常常為會控件添加一些依賴屬性以便於綁定或動畫等。事實上,除了能夠添加正常的依賴屬性外,我們還可以為控件添加只讀依賴屬性(以下統稱“只讀屬性”),以增加控件的靈活性。 這聽

VS2010屬性表的建立靈活運用

如何 新項目 簡化 百度 經驗 table .html 減少 eas 問題引入:在VS2010當中,進行opencv、QT等的編程時,總是需要配置很多屬性還有依賴項等,為了減少每次都重復配置屬性的工作量,現在可以運行屬性表這個東西來簡化配置。opencv也可以這樣建立使

WPF入門教程系列十一——依賴屬性(一)

nts 如果 edev 出現 樣式 語法 寫法 屬性。 結構 一、依賴屬性基本介紹   本篇開始學習WPF的另一個重要內容依賴屬性。 大家都知道WPF帶來了很多新的特性,其中一個就是引入了一種新的屬性機制——依賴屬性。依賴屬性出現的目的是用來實現WPF中的樣式、自

WPF入門教程系列十四——依賴屬性(四)

nan out rmi strong too nim app controls ase 六、依賴屬性回調、驗證及強制值 我們通過下面的這幅圖,簡單介紹一下WPF屬性系統對依賴屬性操作的基本步驟:   借用一個常見的圖例,介紹一下WPF屬性系統對依賴屬性操作的基本

背水一戰 Windows 10 (67) - 控件(控件基類): DependencyObject - CoreDispatcher, 依賴屬性的設置獲取, 依賴屬性的變化回調

protected getprop prop 依賴屬性 其他 優先級 dto type 核心 [源碼下載] 背水一戰 Windows 10 (67) - 控件(控件基類): DependencyObject - CoreDispatcher, 依賴屬性的設置與獲取, 依賴

【轉】【WPF】關於依賴屬性的ValidateValueCallback,PropertyChangedCallback和CoerceValueCallback的執行順序

value read ado args cep img 強制轉換 .cn clas 三個回調對應依賴屬性的驗證過程,改變過程和強制轉換過程。 class Dobj : DependencyObject { //依賴屬性包裝 public int MyPro

WPF屬性(一)依賴屬性

沒有 http readonly har https 默認 lease clr 數據源 原文:WPF屬性(一)依賴屬性 依賴屬性是一種可以自己沒有值,並能通過使用B

說說WPF依賴屬性

eof ML binding The pro 運行程序 nta sent 什麽是 首先,我們先來大概了解一下依賴屬性 什麽是依賴屬性:依賴屬性自己沒有值,通過依賴別人(如Binding)來獲得值。 依賴屬性為什麽會出現:控件常用字段有限,包裝太多屬性會占用過高內存,造成

WPF xaml中列表依賴屬性的定義

9.png hive urn 中一 roo rabl thead pro 標識 原文:WPF xaml中列表依賴屬性的定義列表內容屬性 如上圖,是一個列表標題排序控件,我們需要定義一個標題列表,從而讓調用方可以自由的設置標題信息。 在自定義控件時,會遇到列表依賴屬性

[UWP]為附加屬性依賴屬性自定義程式碼段(相容UWP和WPF

1. 前言 之前介紹過依賴屬性和附加屬性的程式碼段,這兩個程式碼段我用了很多年,一直都幫了我很多。不過這兩個程式碼段我也多年沒修改過,Resharper老是提示我生成的程式碼可以修改,它這麼有誠意,這次就只好從了它,順便簡單介紹下怎麼自定義程式碼段。 2. VisualStudio自帶程式碼段的問題 以

wpf自定義控制元件之依賴屬性

  在wpf開發過程中,總會用到格式各樣的控制元件,但是原生控制元件遠遠不能滿足實際開發的需要,這時候wpf強大之處就能體現出來了。根據實際需求自定義各種不同的控制元件滿足不同的業務需求。 首先說需求吧: 一:根據某個bool值,控制一個圓形控制元件顯示或者不顯示某種顏色。 分析: 一:需