最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C# WPF 中的?屬性示例詳解

 更新時間:2026年02月05日 10:08:44   作者:工業(yè)程序猿老趙  
本文詳細介紹了C# WPF中的屬性,包括基礎的CLR屬性和WPF特有的依賴屬性以及附加屬性,通過實戰(zhàn)和示例,解釋了如何在XAML中使用屬性進行數據綁定、樣式設置和動畫等操作,感興趣的朋友跟隨小編一起看看吧

想要深入淺出地理解 C# WPF 中的?屬性?,核心要區(qū)分「C# 語言本身的屬性」和「WPF 特有的依賴屬性 / 附加屬性」,還要掌握 WPF 中屬性的核心用法(數據綁定、樣式、動畫等)—— 這也是 WPF 數據驅動 UI 的基礎。我會從?基礎到進階?,先講 C# 普通屬性,再過渡到 WPF 的核心屬性體系,結合示例和實際場景講清楚設計思想和用法,保證易懂且貼近實戰(zhàn)。

一、先鋪墊:C# 普通屬性(CLR 屬性)—— WPF 屬性的基礎

WPF 的所有高級屬性都是基于 C# 語言的CLR 屬性(Common Language Runtime 屬性) 實現的,先回顧這個基礎,才能理解 WPF 對屬性的擴展。

1. 什么是 CLR 屬性

CLR 屬性是?字段的封裝?,通過get/set訪問器控制字段的讀寫,核心作用是?封裝數據、添加訪問邏輯?,避免直接操作私有字段。

// 私有字段(實際存儲數據)
private string _name = "默認名稱";
// CLR屬性(對外暴露的訪問接口)
public string Name
{
    get => _name; // 讀訪問器:獲取字段值
    set => _name = value; // 寫訪問器:設置字段值,value是關鍵字,表示傳入的新值
}

2. 帶邏輯的 CLR 屬性(實戰(zhàn)常用)

可以在get/set中添加校驗、計算等邏輯,這是封裝的核心價值:

private int _age;
public int Age
{
    get => _age;
    set
    {
        // 校驗邏輯:年齡不能為負數
        if (value >= 0) 
            _age = value;
        else
            throw new ArgumentException("年齡不能為負數");
    }
}
// 計算屬性:無對應的私有字段,值由其他屬性計算而來
public string AgeDesc
{
    get => _age >= 18 ? "成年人" : "未成年人";
}

3. WPF 中 CLR 屬性的局限

在之前的 MVVM 示例中,我們用 CLR 屬性 +INotifyPropertyChanged實現了?數據變化通知 UI?,但這種方式有明顯局限:

  • 僅能實現「單向通知」,無法讓多個 UI 控件共享一個屬性值且自動同步;
  • 不支持 WPF 的核心特性:?**數據綁定的高級特性(如驗證、轉換)、樣式觸發(fā)、動畫、繼承屬性(如字體、顏色)**?;
  • 性能一般,頻繁更新時通知機制的開銷較高。

正是為了解決這些問題,WPF 設計了依賴屬性(Dependency Property) —— 這是 WPF 屬性體系的?核心?。

二、WPF 核心:依賴屬性(Dependency Property)—— 專為 WPF 設計的屬性

1. 什么是依賴屬性

依賴屬性是?WPF 自定義的屬性系統(tǒng)?,它的核心特點是:?屬性的值不是由自身字段存儲,而是「依賴」于 WPF 的屬性系統(tǒng)(DependencyObject)統(tǒng)一管理?。

簡單理解:普通 CLR 屬性是「自己存值自己用」,依賴屬性是「把值交給 WPF 全局管理,誰需要誰去取」,這種設計讓它天然支持 WPF 的所有高級特性。

2. 依賴屬性的設計初衷(解決什么問題)

WPF 作為?聲明式 UI 框架?,需要屬性支持「動態(tài)變化、共享、擴展」,依賴屬性完美解決:

  1. ?屬性值繼承?:子控件自動繼承父控件的屬性(如 Window 設置 FontSize,內部所有 TextBlock 自動繼承);
  2. ?動態(tài)值解析?:屬性值可來自樣式、數據綁定、動畫、模板等,WPF 會自動解析優(yōu)先級;
  3. ?輕量級存儲?:大量控件的相同屬性(如 Visibility)默認值一致,WPF 僅存儲「修改過的屬性值」,節(jié)省內存;
  4. ?變更通知?:內置屬性值變化通知,無需手動實現INotifyPropertyChanged;
  5. ?支持附加行為?:如數據驗證、樣式觸發(fā)、動畫綁定。

3. 依賴屬性的核心規(guī)則(必記)

  • 必須定義在繼承自 DependencyObject的類中(WPF 所有控件如 Button、TextBox、Window 都繼承自 DependencyObject);
  • 必須是公共靜態(tài)只讀的字段,類型為DependencyProperty,命名規(guī)范:屬性名 + Property(如TextProperty);
  • 必須通過?CLR 屬性包裝?,對外暴露常規(guī)的get/set,內部調用GetValue/SetValue(WPF 屬性系統(tǒng)的核心方法);
  • 必須通過DependencyProperty.Register方法注冊到 WPF 屬性系統(tǒng)中。

4. 實戰(zhàn) 1:自定義一個依賴屬性(最基礎示例)

我們以「自定義一個帶MyText依賴屬性的控件」為例,一步一步實現,理解核心寫法:

using System.Windows;
using System.Windows.Controls;
// 自定義控件:繼承自Control(間接繼承DependencyObject)
public class MyCustomControl : Control
{
    // 1. 注冊依賴屬性:公共靜態(tài)只讀字段,命名規(guī)范【屬性名+Property】
    public static readonly DependencyProperty MyTextProperty =
        DependencyProperty.Register(
            nameof(MyText), // 依賴屬性對應的CLR屬性名(必須一致)
            typeof(string), // 屬性的類型
            typeof(MyCustomControl), // 所屬的控件類型
            new PropertyMetadata( // 屬性元數據:設置默認值、變化回調等
                "默認文本", // ① 屬性默認值
                OnMyTextChanged // ② 屬性值變化時的回調方法(可選)
            )
        );
    // 2. CLR屬性包裝:對外暴露常規(guī)訪問方式,內部調用GetValue/SetValue
    public string MyText
    {
        get => (string)GetValue(MyTextProperty); // 從WPF屬性系統(tǒng)取值
        set => SetValue(MyTextProperty, value); // 向WPF屬性系統(tǒng)賦值
    }
    // 3. 可選:屬性值變化的回調方法(處理邏輯,如通知UI、更新其他屬性)
    private static void OnMyTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        // d:當前控件實例;e:變化參數(OldValue舊值,NewValue新值)
        var control = (MyCustomControl)d;
        string oldText = (string)e.OldValue;
        string newText = (string)e.NewValue;
        // 這里可以添加屬性變化后的邏輯,比如更新控件樣式、觸發(fā)事件等
        control.ToolTip = $"文本從「{oldText}」改為「{newText}」";
    }
}

5. 實戰(zhàn) 2:在 XAML 中使用自定義依賴屬性

定義好依賴屬性后,就可以像使用 WPF 原生控件的屬性(如 Button 的 Content)一樣在 XAML 中使用,支持?數據綁定、樣式、靜態(tài)賦值?:

<!-- 引用自定義控件的命名空間(假設命名空間是WpfPropertyDemo) -->
<Window x:Class="WpfPropertyDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfPropertyDemo"
        Title="依賴屬性示例" Height="200" Width="300">
    <StackPanel Spacing="10" HorizontalAlignment="Center" VerticalAlignment="Center">
        <!-- 1. 靜態(tài)賦值:直接設置MyText -->
        <local:MyCustomControl MyText="我是自定義控件" Width="200" Height="50" Background="LightBlue"/>
        <!-- 2. 數據綁定:和ViewModel的屬性關聯(lián)(支持WPF所有綁定特性) -->
        <local:MyCustomControl MyText="{Binding ViewModelText}" Width="200" Height="50" Background="LightGreen"/>
    </StackPanel>
</Window>

6. 實戰(zhàn) 3:使用 WPF 原生依賴屬性(開發(fā)中最常用)

實際開發(fā)中,我們?很少自定義依賴屬性?,更多是使用 WPF 原生控件的依賴屬性(如 TextBox 的Text、Button 的Command、TextBlock 的Foreground),結合數據綁定實現核心功能 —— 這也是之前 MVVM 示例的基礎:

<!-- 原生依賴屬性的核心用法:數據綁定 -->
<TextBox Text="{Binding UserName, Mode=TwoWay}"/>
<Button Content="確認" Command="{Binding ConfirmCommand}"/>
<TextBlock Foreground="{Binding TipColor}" Text="{Binding TipMessage}"/>

這些Text/Content/Foreground都是 WPF 內置的依賴屬性,天然支持數據綁定、樣式、動畫等特性。

三、WPF 進階:附加屬性(Attached Property)—— 「跨控件」的依賴屬性

1. 什么是附加屬性

附加屬性是?依賴屬性的特殊形式?,核心特點是:?屬性定義在 A 類中,但可以被 B 類(繼承自 DependencyObject)使用?,簡單說就是「?借屬性用?」。

設計初衷:解決控件之間的布局 / 關系屬性問題 —— 比如布局控件(Grid、StackPanel)需要控制子控件的布局(如 Grid 的行 / 列),但子控件(Button、TextBox)本身不需要內置這些布局屬性,此時就可以用附加屬性。

2. 核心規(guī)則(與依賴屬性的區(qū)別)

  • 同樣繼承自DependencyObject,注冊方法不是Register,而是 **RegisterAttached**;
  • 沒有常規(guī)的 CLR 屬性包裝,而是提供靜態(tài)的GetXXX/SetXXX方法供外部調用;
  • 命名規(guī)范和依賴屬性一致:屬性名 + Property。

3. 最經典的示例:Grid 的附加屬性

WPF 中 Grid 的Grid.Row/Grid.Column是最常用的附加屬性,定義在Grid類中,但可以被所有子控件使用:

<!-- Grid.Row/Grid.Column是Grid的附加屬性,被Button/TextBox使用 -->
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition/>
    </Grid.RowDefinitions>
    <!-- Button使用Grid的Row附加屬性,指定在第0行 -->
    <Button Grid.Row="0" Content="第0行按鈕"/>
    <!-- TextBox使用Grid的Row附加屬性,指定在第1行 -->
    <TextBox Grid.Row="1" PlaceholderText="第1行輸入框"/>
</Grid>

底層原理:Grid 在布局時,會通過Grid.GetRow(控件)獲取附加屬性的值,然后根據值排列子控件。

4. 實戰(zhàn):自定義一個附加屬性(理解底層)

我們實現一個「自定義附加屬性MyAttachProperty」,讓所有控件都能設置「是否顯示邊框」,一步一步來:

using System.Windows;
using System.Windows.Controls;
// 附加屬性的定義類(可任意類,只要靜態(tài)方法+注冊Attached)
public static class MyAttachHelper
{
    // 1. 注冊附加屬性:使用RegisterAttached
    public static readonly DependencyProperty ShowBorderProperty =
        DependencyProperty.RegisterAttached(
            "ShowBorder", // 附加屬性名
            typeof(bool), // 屬性類型
            typeof(MyAttachHelper), // 所屬類
            new PropertyMetadata(false, OnShowBorderChanged) // 默認值false,變化回調
        );
    // 2. 公共靜態(tài)Get方法:供外部獲取屬性值(命名規(guī)范:Get+屬性名)
    public static bool GetShowBorder(DependencyObject obj)
    {
        return (bool)obj.GetValue(ShowBorderProperty);
    }
    // 3. 公共靜態(tài)Set方法:供外部設置屬性值(命名規(guī)范:Set+屬性名)
    public static void SetShowBorder(DependencyObject obj, bool value)
    {
        obj.SetValue(ShowBorderProperty, value);
    }
    // 4. 屬性值變化的回調:處理邏輯(給控件加/去邊框)
    private static void OnShowBorderChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        // d是使用該附加屬性的控件實例,判斷是否是FrameworkElement(所有可視化控件的基類)
        if (d is FrameworkElement element)
        {
            bool isShow = (bool)e.NewValue;
            // 根據值設置邊框:如果是Button/TextBox,直接設置BorderBrush和BorderThickness
            if (element is Button button)
            {
                button.BorderBrush = isShow ? Brushes.Black : Brushes.Transparent;
                button.BorderThickness = isShow ? new Thickness(1) : new Thickness(0);
            }
            else if (element is TextBox textBox)
            {
                textBox.BorderBrush = isShow ? Brushes.Red : Brushes.Gray;
                textBox.BorderThickness = isShow ? new Thickness(2) : new Thickness(1);
            }
        }
    }
}

5. 在 XAML 中使用自定義附加屬性

和使用原生附加屬性一樣,通過「?命名空間。類名。屬性名?」的方式設置,所有 WPF 控件都能使用:

<Window x:Class="WpfPropertyDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfPropertyDemo"
        Title="附加屬性示例" Height="200" Width="300">
    <StackPanel Spacing="10" HorizontalAlignment="Center" VerticalAlignment="Center">
        <!-- Button使用自定義附加屬性:顯示黑色邊框 -->
        <Button local:MyAttachHelper.ShowBorder="True" Content="帶邊框按鈕" Width="100"/>
        <!-- TextBox使用自定義附加屬性:顯示紅色粗邊框 -->
        <TextBox local:MyAttachHelper.ShowBorder="True" PlaceholderText="帶邊框輸入框" Width="200"/>
        <!-- 普通TextBlock:不設置,默認無邊框 -->
        <TextBlock Text="無邊框文本" Width="200"/>
    </StackPanel>
</Window>

四、WPF 屬性的核心知識點:值優(yōu)先級(必懂)

WPF 的依賴屬性 / 附加屬性支持?多來源賦值?(如默認值、樣式、數據綁定、動畫、代碼手動設置),當一個屬性被多個來源賦值時,WPF 會按照固定的優(yōu)先級解析最終值,優(yōu)先級從依次為:

  1. 動畫正在運行的值 → 2. 代碼手動設置的本地值(如button.Content = "測試") → 3. 數據綁定的值 → 4. 樣式觸發(fā)器 → 5. 樣式設置 → 6. 繼承的值(如父控件的 FontSize) → 7. 屬性的默認值(PropertyMetadata 中設置)。

?示例?:如果給 Button 的Content同時設置「樣式默認值 = 按鈕」、「數據綁定 = ViewModel.Text」、「代碼設置 = 測試」,最終 Button 顯示?測試?(本地值優(yōu)先級最高)。

這個規(guī)則能幫你解決開發(fā)中「屬性值不生效」的問題 —— 比如動畫運行時,數據綁定的屬性值會被覆蓋,動畫結束后才會恢復。

五、CLR 屬性 vs 依賴屬性 vs 附加屬性(核心對比)

為了讓你快速區(qū)分和選擇,用表格總結三者的核心區(qū)別、使用場景:

類型核心特點存儲方式定義位置核心使用場景
CLR 屬性C# 原生,get/set 封裝字段私有字段自行存儲任意類ViewModel 中的數據屬性(需配合 INotifyPropertyChanged)
依賴屬性WPF 自定義,支持高級特性WPF 屬性系統(tǒng)統(tǒng)一管理繼承 DependencyObject 的類WPF 控件的核心屬性(如 Text、Content)、自定義控件的屬性
附加屬性依賴屬性的特殊形式,跨控件使用WPF 屬性系統(tǒng)統(tǒng)一管理任意類(靜態(tài)方法)布局控制(Grid.Row)、跨控件的通用屬性(如自定義附加行為)

?核心選擇原則?:

  1. ?ViewModel 層?:用?CLR 屬性 + INotifyPropertyChanged?(ViewModel 不需要繼承 DependencyObject,方便單元測試);
  2. ?View 層(控件 / 自定義控件)?:用?依賴屬性?(支持數據綁定、樣式等 WPF 特性);
  3. ?跨控件的通用屬性 / 布局?:用?附加屬性?(如讓所有控件都能設置某個通用特性)。

六、WPF 屬性與數據驅動 UI 的關聯(lián)(回歸核心)

WPF 的數據驅動 UI核心是「?數據綁定 + 屬性變化通知?」,而屬性是這個核心的基礎:

  1. ViewModel 的CLR 屬性通過INotifyPropertyChanged實現「數據變化→通知 WPF」;
  2. View 層控件的依賴屬性天然支持「數據綁定」,WPF 監(jiān)聽到 ViewModel 的通知后,自動更新依賴屬性的值,進而刷新 UI;
  3. 依賴屬性的內置變更通知讓控件自身的屬性變化時,也能觸發(fā) UI 刷新(如 Slider 的 Value 變化,觸發(fā) TextBlock 的 Text 更新)。

簡單說:?沒有 WPF 的屬性體系,就沒有數據驅動 UI 的實現?。

總結

  1. ?基礎?:CLR 屬性是 C# 原生封裝,ViewModel 層專用,需配合INotifyPropertyChanged實現數據通知;
  2. ?核心?:依賴屬性是 WPF 的靈魂,定義在繼承DependencyObject的類中,支持數據綁定、樣式、動畫等所有高級特性,View 層控件的屬性均為依賴屬性;
  3. ?擴展?:附加屬性是跨控件的依賴屬性,通過Get/Set靜態(tài)方法使用,核心用于布局和跨控件的通用屬性;
  4. ?關鍵規(guī)則?:依賴屬性 / 附加屬性的值由 WPF 屬性系統(tǒng)管理,遵循?值優(yōu)先級?,解決多來源賦值的沖突;
  5. ?核心關聯(lián)?:WPF 的屬性體系是數據驅動 UI 的基礎,CLR 屬性負責 ViewModel 的數封裝,依賴屬性負責 View 層的 UI 綁定和刷新。

到此這篇關于深入淺出地理解 C# WPF 中的?屬性的文章就介紹到這了,更多相關C# WPF屬性內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • 詳解WPF如何把checkbox改成開關樣式

    詳解WPF如何把checkbox改成開關樣式

    這篇文章主要為大家詳細介紹了WPF如何把checkbox改成開關樣式,文中的示例代碼講解詳細,具有一定的借鑒價值,有需要的小伙伴可以參考一下
    2024-11-11
  • C#結合Spire.Doc for .NET實現智能復制Word文檔內容

    C#結合Spire.Doc for .NET實現智能復制Word文檔內容

    在日常的開發(fā)工作或文檔處理中,我們常常需要將一個Word文檔中的內容復制到另一個文檔,本文將為您揭示如何利用C#編程語言與強大的Spire.Doc for .NET庫,實現Word文檔內容的智能復制,感興趣的小伙伴可以了解下
    2026-01-01
  • unity shader 較完整光照(含有多光源陰影)

    unity shader 較完整光照(含有多光源陰影)

    這篇文章主要介紹了unity shader 較完整光照(含有多光源陰影),本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-09-09
  • C#簡單數字圖像處理程序

    C#簡單數字圖像處理程序

    這篇文章主要為大家詳細介紹了C#簡單數字圖像處理程序,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-09-09
  • C# 文件下載之斷點續(xù)傳實現代碼

    C# 文件下載之斷點續(xù)傳實現代碼

    本篇文章主要介紹了C# 文件下載之斷點續(xù)傳實現代碼,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-01-01
  • C# XAML中x:Type的用法詳解

    C# XAML中x:Type的用法詳解

    x:Type是 XAML 中獲取.NET 類型Type對象的核心工具,主要用于泛型類型聲明、依賴屬性的 Type 參數設置、反射場景的類型傳遞等,本文介紹C# XAML中x:Type的用法,感興趣的朋友跟隨小編一起看看吧
    2025-12-12
  • C#實現奇偶排序的示例代碼

    C#實現奇偶排序的示例代碼

    奇偶排序是一種簡單的排序算法,該算法通過比較并交換相鄰的元素來完成排序,本文主要介紹了C#實現奇偶排序的示例代碼,具有一定的參考價值,感興趣的可以了解一下
    2023-11-11
  • C#中讀寫INI配置文件的方法

    C#中讀寫INI配置文件的方法

    這篇文章主要介紹了C#中讀寫INI配置文件的方法,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
    2018-07-07
  • C#索引屬性用法實例分析

    C#索引屬性用法實例分析

    這篇文章主要介紹了C#索引屬性用法,實例分析了C#聲明索引屬性的相關技巧,需要的朋友可以參考下
    2015-06-06
  • Unity中協(xié)程IEnumerator的使用方法介紹詳解

    Unity中協(xié)程IEnumerator的使用方法介紹詳解

    本文主要介紹了Unity中協(xié)程IEnumerator的使用方法介紹詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-06-06

最新評論

泽普县| 新津县| 襄樊市| 宽城| 虎林市| 平阴县| 大名县| 昆山市| 泾源县| 安溪县| 阿图什市| 宝鸡市| 玛沁县| 长垣县| 乌什县| 泾源县| 北碚区| 正镶白旗| 五台县| 大埔区| 铁岭市| 泌阳县| 隆德县| 罗田县| 张掖市| 吉木乃县| 江华| 习水县| 靖边县| 玉树县| 全州县| 荆州市| 汤阴县| 通化市| 绿春县| 灵武市| 尤溪县| 蚌埠市| 怀集县| 施秉县| 盖州市|