文章目錄
- 一、用戶控價
- 1.1 依賴屬性的注冊
- 1.2 具體使用
一、用戶控價
1.1 依賴屬性的注冊
using System.Windows;
using System.Windows.Controls;namespace WpfApp
{public partial class MyUserControl : UserControl{// 依賴屬性:外部可綁定的文本public static readonly DependencyProperty TextProperty =DependencyProperty.Register("Text",typeof(string),typeof(MyUserControl),new FrameworkPropertyMetadata(string.Empty,FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,OnTextPropertyChanged));public string Text{get => (string)GetValue(TextProperty);set => SetValue(TextProperty, value);}// 自定義事件:提交按鈕點擊public static readonly RoutedEvent SubmitClickedEvent =EventManager.RegisterRoutedEvent("SubmitClicked",RoutingStrategy.Bubble,typeof(RoutedEventHandler),typeof(MyUserControl));public event RoutedEventHandler SubmitClicked{add => AddHandler(SubmitClickedEvent, value);remove => RemoveHandler(SubmitClickedEvent, value);}public MyUserControl(){InitializeComponent();DataContext = new MyUserControlViewModel(this);}private static void OnTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e){var control = (MyUserControl)d;control.RaiseEvent(new RoutedEventArgs(SubmitClickedEvent));}}
}
這段代碼是在WPF中注冊依賴屬性(Dependency Property) 的標準寫法,下面來詳細解釋它的作用和參數含義:
1. 函數整體作用
DependencyProperty.Register
是WPF中創建依賴屬性的核心方法。它做了兩件事:
- 定義屬性元數據:包括屬性名稱、類型、所有者類型、默認值等。
- 返回屬性標識符:通過靜態字段(如
TextProperty
)保存,用于后續通過GetValue/SetValue
訪問屬性值。
2. 參數詳解
public static readonly DependencyProperty TextProperty =DependencyProperty.Register("Text", // 參數1:屬性名稱(字符串)typeof(string), // 參數2:屬性類型(Type)typeof(MyUserControl), // 參數3:所有者類型(Type)new FrameworkPropertyMetadata( // 參數4:元數據string.Empty, // 默認值FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, // 綁定模式OnTextPropertyChanged // 值變更回調));
參數1:“Text”
- 含義:這是依賴屬性的名稱,必須與CLR包裝器屬性名一致(即類中的
public string Text { get; set; }
)。 - 作用:WPF內部通過這個名稱識別屬性,例如在XAML中使用
<MyUserControl Text="Hello" />
。
參數2:typeof(string)
- 含義:屬性的類型,這里是字符串類型。
- 作用:確保屬性值類型安全,WPF會自動進行類型檢查。
參數3:typeof(MyUserControl)
- 含義:聲明該依賴屬性的所有者類型,即哪個類擁有這個屬性。
- 作用:允許同一個依賴屬性被多個類共享(通過
AddOwner
方法),但這里MyUserControl
是原始所有者。
參數4:FrameworkPropertyMetadata
- 默認值(string.Empty):屬性未被顯式設置時的默認值。
- 綁定模式(BindsTwoWayByDefault):
- 表示此屬性的默認綁定模式是雙向綁定(
Mode=TwoWay
)。 - 例如:
<MyUserControl Text="{Binding SomeValue}" />
會自動成為雙向綁定。
- 表示此屬性的默認綁定模式是雙向綁定(
- 回調方法(OnTextPropertyChanged):
- 當屬性值變化時,WPF會自動調用這個靜態方法。
- 常用于實現屬性變更通知或依賴操作。
3. 參數"Text"屬于誰?
參數 "Text"
是 MyUserControl
類的公共屬性。通過依賴屬性機制,這個屬性:
- 可在XAML中直接使用:
<local:MyUserControl Text="直接設置值" />
- 支持數據綁定:
<local:MyUserControl Text="{Binding ViewModelProperty}" />
- 可通過代碼訪問:
myUserControl.Text = "通過代碼設置";
4. 依賴屬性 vs 普通屬性
特性 | 普通屬性 | 依賴屬性 |
---|---|---|
存儲方式 | 實例字段(如 private string _text ) | 由WPF屬性系統統一管理 |
默認值 | 在構造函數中設置 | 通過元數據設置(全局唯一) |
數據綁定 | 需要手動實現 INotifyPropertyChanged | 原生支持,自動通知 |
樣式/動畫支持 | 不支持 | 支持(可被樣式覆蓋、可動畫化) |
繼承性 | 無 | 部分屬性支持值繼承(如 FontSize ) |
※※※
5. 完整工作流程
-
注冊階段:
- 通過
DependencyProperty.Register
創建屬性定義。 - 靜態字段
TextProperty
保存屬性標識符。
- 通過
-
CLR包裝器(可選但推薦):
public string Text {get => (string)GetValue(TextProperty);set => SetValue(TextProperty, value); }
-
使用階段:
- XAML中:
<MyUserControl Text="值" />
- 代碼中:
myControl.Text = "值";
- 數據綁定時:WPF通過
TextProperty
標識符解析屬性。
- XAML中:
總結
- “Text” 參數:是
MyUserControl
類的公共屬性名,用于外部訪問。 - 依賴屬性機制:讓屬性具備動態值解析、數據綁定、樣式支持等高級特性,是WPF控件開發的核心技術。
1.2 具體使用
MainWindow.xaml
<Window x:Class="WpfApp2.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:WpfApp2"mc:Ignorable="d"Title="MainWindow" Height="450" Width="800"><Grid><StackPanel><local:UserControl1 Margin="10" Height="200" Width="250" x:Name="userControl"/><Button Content="button1" Click="Button_Click_1"/><Button Content="button2" Click="Button_Click_2"/></StackPanel></Grid>
</Window>
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 WpfApp2
{/// <summary>/// MainWindow.xaml 的交互邏輯/// </summary>public partial class MainWindow : Window{public MainWindow(){InitializeComponent();}private void Button_Click_1(object sender, RoutedEventArgs e){userControl.Text = "你大爺";}private void Button_Click_2(object sender, RoutedEventArgs e){userControl.Text = "你 好";}}
}
UserControl1.xaml
<UserControl x:Class="WpfApp2.UserControl1"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:WpfApp2"mc:Ignorable="d" d:DesignHeight="100" d:DesignWidth="200"><Grid><TextBox x:Name="txtInput" Margin="10" /><Button Content="提交" Click="Button_Click" Margin="10,50,10,10" /><TextBlock x:Name="lblOutput" Margin="10,90,10,10" /></Grid>
</UserControl>
UserControl1.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 WpfApp2
{/// <summary>/// UserControl1.xaml 的交互邏輯/// </summary>public partial class UserControl1 : UserControl{public UserControl1(){InitializeComponent();}private void Button_Click(object sender, RoutedEventArgs e){lblOutput.Text = "你輸入的是:" + txtInput.Text;}public static readonly DependencyProperty TextProperty =DependencyProperty.Register("Text", // 屬性名typeof(string), // 屬性類型typeof(UserControl1), // 所有者類型new PropertyMetadata( // 元數據string.Empty, // 默認值OnTextPropertyChanged // 值變更回調));public string Text{get => (string)GetValue(TextProperty);set => SetValue(TextProperty, value);}private static void OnTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e){var control = (UserControl1)d;control.lblOutput.Text = "屬性值:" + e.NewValue;}}
}