在正文開始之前需要介紹一個人:Sean Sexton. 來自明尼蘇達雙城的軟件工程師。最為出色的是他維護了兩個博客:2,000Things You Should Know About C# 和 2,000 Things You Should Know About WPF 。他以類似微博式的150字簡短語言來每天更新一條WPF和C#重要又容易被遺忘的知識。Follow他的博客也有一段日子了,很希望能夠分享給大家。
本系列我不僅會翻譯他的每一個tip,也會加入自己開發之中的看法和見解。本系列我希望自己也能和他一樣堅持下來,每天的進步才能促成偉大。
在這里鄭重說明.該系列是基於Sean Sexton先生的英文博客, Sean Sexton擁有全部版權和撤銷權利。
前文:<1-7> , <8-14>,<15-21>22-27>, <28-33>,<34-39>,<40-44>,<45-50>
[小九的學堂,致力於以平凡的語言描述不平凡的技術。如要轉載,請注明來源:小九的學堂。cnblogs.com/xfuture]
#57 依賴屬性值變化時的通知事件
當一個依賴屬性值改變的時候,實現它的類可以隨時得知其改變。當該類注冊該依賴屬性的時候可以指定PropertyChangedCallback來獲取其事件。
PropertyMetadata ageMetadata = new PropertyMetadata( 18, // Default value new PropertyChangedCallback(OnAgeChanged), // ** call when property changes new CoerceValueCallback(OnAgeCoerceValue)); // Register the property AgeProperty = DependencyProperty.Register( "Age", // Property's name typeof(int), // Property's type typeof(Person), // Defining class' type ageMetadata, // Defines default value & callbacks (optional) new ValidateValueCallback(OnAgeValidateValue)); // validation (optional)
該類可以通過回調的函數才處理當值改變時候的邏輯。比如通過一個值的改變影響另一個值。
private static void OnAgeChanged (DependencyObject depObj, DependencyPropertyChangedEventArgs e) { Person p = (Person)depObj; p.AARPCandidate = (int)e.NewValue > 60 ? true : false; }
#58 驗證依賴屬性
注冊依賴屬性時,可以進行驗證回調。當依賴屬性被指定一個新值得時候,可以先通過驗證函數驗證,返回true or false來表示其是否有效。當注冊這個依賴屬性的時候可以指定其驗證回調函數。
AgeProperty = DependencyProperty.Register( "Age", // Property's name typeof(int), // Property's type typeof(Person), // Defining class' type ageMetadata, // Defines default value & changed/coercion callbacks (optional) new ValidateValueCallback(OnAgeValidateValue)); // *** validation (optional)
驗證回調函數可以對新值進行驗證
private static bool OnAgeValidateValue (object value) { int age = (int) value; // Only allow reasonable ages return (age > 0) && (age < 120); }
如果值不能被接受,則拋出exception
Person p = new Person("Samuel", "Clemens"); p.Age = 40; // ok p.Age = 300; // throws System.ArgumentException
#59 強制改變依賴屬性值
人在做事的時候,都需要考慮一個底線,很多時候做了過分的事情你就期望有人提醒你,“嗨,這個事情你越線了!”。依賴屬性就有一個特性,可以在你越線的時候把你拉回底線。那就是CoerceValueCallback。當你apple新的value的時候,它是最后一層安全系數。
你可以在定義這個依賴屬性的時候,定義CoerceValueCallback.
PropertyMetadata ageMetadata = new PropertyMetadata( 18, // Default value new PropertyChangedCallback(OnAgeChanged), new CoerceValueCallback(OnAgeCoerceValue)); // ** allow class to coerce value // Register the property AgeProperty = DependencyProperty.Register( "Age", // Property's name typeof(int), // Property's type typeof(Person), // Defining class' type ageMetadata, // Defines default value & changed/coercion callbacks (optional) new ValidateValueCallback(OnAgeValidateValue)); // validation (optional)
你可以在delegate的OnAgeCoerceValue方法里來控制它的界限,並給予其新值。
private static object OnAgeCoerceValue (DependencyObject depObj, object baseValue) { int coercedValue = (int)baseValue; if ((int)baseValue > 120) coercedValue = 120; if ((int)baseValue < 1) coercedValue = 1; return coercedValue; }
#60 Wpf中基於依賴屬性特性實現的一個例子
依賴屬性有三種回調函數類可以來進行控制:
1. PropertyChangedCallback 當獲取一個新值得時候觸發
2. ValidateValueCallback 決定值是否有效
3. CoerceValueCallback 強制更改為其他值
DataGrid.FrozenColumnCount是一個三種邏輯都實現了的例子。
1. PropertyChangedCallback. 渲染標題的時候,使之能正確顯示。
2. ValidateValueCallback 驗證是否為負值。
3. CoerceValueCallback 如果賦予的值大於其行數,則強制為最大值。
#61 響應變化
在WPF編程中對依賴屬性除了使用PropertyChangedCallback事件來進行響應變化,還有其他方式。
有兩種方式可以做到:
1. Data Binding
2. Triggers
#62 Triggers
下面介紹Triggers。可以通過觸發器Triggers來響應值變化時引起的蝴蝶效應。
由於觸發器只能針對離散值。所以下面的例子是簡單的布爾值關聯的觸發器Trigger
<CheckBox Content="Check Me" HorizontalAlignment="Center"> <CheckBox.Style> <Style TargetType="CheckBox"> <Style.Triggers> <Trigger Property="IsChecked" Value="true"> <Setter Property="Foreground" Value="BlueViolet"/> </Trigger> </Style.Triggers> </Style> </CheckBox.Style> </CheckBox>
但該checkbox選中的時候,字體會被觸發更改為BlueViolet.這邊是trigger實現值變化時蝴蝶效應的方法。
而且Triggers是不需要在后台代碼中寫任何code的。只需要在xaml中就可以實現邏輯。