WPF之所以後續越來越多人使用,就是因為它的Dependency Property And Callback,甚至拉動Flex Windows的時候也不會讓圖片與元Dpi跑掉,以前的經驗表示… 在A端IDE跑得好好的外觀屬性,換到B端時…外觀屬性跑掉是家常便飯,一時之間會不知道是內層還是外部的設定屬性造成的(這個就會與WPF-Dependency Property有很大的關係)。
以前的NetFramework 沒有Dpi適應以及元件外觀沒有相依性可以跟著整個Solutioni走,所以開發WPF(Windows Presentation Foundation)的大神也肯定有察覺到這個超級不方便的地方。
今天我們就是要講這其中的一個重要元素 – Dependency Property。
資料來源:
https://skychang.github.io/2011/12/15/WPF-Dependency-Property-%E6%B7%B1%E5%85%A5%E6%8E%A2%E8%A8%8E/
表單資料架構
以前的 Property寫法
在看Dependency Property之前,先來看看,以前的Property是什麼格式。
private double fntsize;
public double FontSize
{
get { return fntsize; }
set { fntsize = value; }
}
你如果使用這種動態的方式,還得去定義FontChangedEvent 再去RaiseEvent … 真的很痛苦!
WPF不需要這樣子搞了!
在Visual Studio中添加Dependency Property
在Visual Studio中的Dependency Class中加入一個靜態Dependency Property。
DependencyProperty只能被封裝在繼承DependencyObject的物件中,幾乎在WPF或是Silverlight中看得到的控制項都繼承了DependencyObject,這跟我們之前用的 CLR屬性相差非常地多。
Dependency Property Callback 示範
// 建立靜態DependencyProperty
// 相依屬性的元資料。這裡設定了初始值為 false,以及屬性值改變時要呼叫的方法
public static DependencyProperty IsBrownBkgrdProperty =
DependencyProperty.Register("IsBrownBkgrd", typeof(bool), typeof(MLStackPanel), new PropertyMetadata(false, OnIsBrownBkgrdChanged, CoerceIsBrownBkgrdChanged));
當我們必須操控Form 裡面的原件屬性,需按照我們定義的方式做變化時,我們可以在Dependency Property 註冊的地方新增一個…
內部可以多載的實體 PropertyMetadata ( Boolean,PropertyChangedCallBack, CoreceValueCallBack)
*可以想像它是被包裹在Dependency Property裡面的實體物件
Boolean
預先設定布林值
PropertyChangedCallBack
可改變實體元件的屬性值
CoreceValueCallBack
讀取目前元件底下的屬性值
建立靜態DependencyProperty
namespace CustomDependencyProperty
{
class MLStackPanel : StackPanel
{
// 建立靜態DependencyProperty
// 相依屬性的元資料。這裡設定了初始值為 false,以及屬性值改變時要呼叫的方法
public static DependencyProperty IsBrownBkgrdProperty =
DependencyProperty.Register("IsBrownBkgrd", typeof(bool), typeof(MLStackPanel), new PropertyMetadata(false, OnIsBrownBkgrdChanged, CoerceIsBrownBkgrdChanged));
}
Dependency Property 宣告與新增其CLR屬性
namespace CustomDependencyProperty
{
class MLStackPanel : StackPanel
{
// 建立靜態DependencyProperty
// 相依屬性的元資料。這裡設定了初始值為 false,以及屬性值改變時要呼叫的方法
public static DependencyProperty IsBrownBkgrdProperty =
DependencyProperty.Register("IsBrownBkgrd", typeof(bool), typeof(MLStackPanel), new PropertyMetadata(false, OnIsBrownBkgrdChanged, CoerceIsBrownBkgrdChanged));
// 建立靜態物件 判斷StackPanel 控制項背景顏色
private static object CoerceIsBrownBkgrdChanged(DependencyObject d, object baseValue)
{
MLStackPanel m = d as MLStackPanel;
if (m.IsBrownBkgrd == false)
{
MessageBox.Show("The IsBrownBkgrd depdendency property is being changed to true");
return true;
}
else
{
MessageBox.Show("The IsBrownBkgrd depdendency property is being changed to false");
return false;
}
}
//CLR 屬性包裹
public bool IsBrownBkgrd
{
get { return (bool)GetValue(IsBrownBkgrdProperty); }
set { SetValue(IsBrownBkgrdProperty, value); }
}
當你建立完了MLStackPanel Class之後,我們會將這個Property加到我們的自訂控制項中(MainForm的XAML碼),讓我們更容易理解。
我們需要一個偵測背景顏色的副程式
namespace CustomDependencyProperty
{
//繼承 控制項 StackPanel
class MLStackPanel : StackPanel
{
// 建立靜態DependencyProperty
// 相依屬性的元資料。這裡設定了初始值為 false,以及屬性值改變時要呼叫的方法
public static DependencyProperty IsBrownBkgrdProperty =
DependencyProperty.Register("IsBrownBkgrd", typeof(bool), typeof(MLStackPanel), new PropertyMetadata(false, OnIsBrownBkgrdChanged, CoerceIsBrownBkgrdChanged));
// 建立靜態物件 判斷StackPanel 控制項背景顏色
private static object CoerceIsBrownBkgrdChanged(DependencyObject d, object baseValue)
{
MLStackPanel m = d as MLStackPanel;
if (m.IsBrownBkgrd == false)
{
MessageBox.Show("The IsBrownBkgrd depdendency property is being changed to true");
return true;
}
else
{
MessageBox.Show("The IsBrownBkgrd depdendency property is being changed to false");
return false;
}
}
//CLR 屬性包裹
public bool IsBrownBkgrd
{
get { return (bool)GetValue(IsBrownBkgrdProperty); }
set { SetValue(IsBrownBkgrdProperty, value); }
}
// 靜態判斷物件
private static object CoerceIsBrownBkgrdChanged(DependencyObject d, object baseValue)
{
MLStackPanel m = d as MLStackPanel;
if (m.IsBrownBkgrd == false)
{
MessageBox.Show("The IsBrownBkgrd depdendency property is being changed to true");
return true;
}
else
{
MessageBox.Show("The IsBrownBkgrd depdendency property is being changed to false");
return false;
}
}
// OnIsBrownBkgrdChanged 方法
private static void OnIsBrownBkgrdChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
{
MLStackPanel msp = source as MLStackPanel;
if (msp.IsBrownBkgrd == true)
{
msp.Background = System.Windows.Media.Brushes.BurlyWood;
}
else
{
msp.Background = System.Windows.Media.Brushes.LightGray;
}
}
}
WPF頁面
該專案目的:
我們得把專案挪用到任何VS的環境,它都能幫助我且準確的保留上一個開發者的外觀樣式。
設定控制項內部的 裝飾屬性
<local:ClassName>:將已經繼承控制項類別的Class 引入
XAML
<Grid>
<local:MLStackPanel x:Name="mlStack" IsBrownBkgrd="true" >
<CheckBox x:Name="chkBkgColor" Content="Brown Background" IsChecked="True" Margin="77,117,0,0" Click="bkgColor_Click" />
</local:MLStackPanel>
</Grid>