DependencyProperty:审定,胁迫及变化处理(第二部分:Silverlight的)

来源:互联网 发布:在淘宝上卖什么最简单 编辑:程序博客网 时间:2024/06/03 21:48

 的DependencyProperty:审定,胁迫及变化处理

简介

这是就如何落实与验证,胁迫和变化通知WPF和Silverlight相依性属​​性的三部分系列的第二部分。 这篇文章的重点在Silverlight。由于Silverlight属性系统支持,开发人员只PropertyChangedCallback实现像WPFCoerceValueCallback和ValidateValueCallback使用PropertyChangedCallback和局部变量。这可能会变得非常棘手,在Silverlight中的错误,因为它会被显示RangeBase控制后系列的第三部分。建议您阅读DependencyProeprty:审定,胁迫及变化处理(第一部分:WPF)的一些背景:WPF属性系统的工作原理,实施WPF依赖属性的模式,简单的例子概述我们将重新与Silverlight在这个岗位实施。

Silverlight相依性属​​性的概述

MSDN有一个良好的依赖项属性概述用于 Silverlight的,这是一个必须阅读,任何人要落实在Silverlight相依性属性。在这里,我刚调出的三个核心类和Silverlight的产权制度的编程接口的两个重要方法,正如我在WPF的第 I部分:

  • DependencyProperty的 :Silverlight的DependencyProperty的是比WPF的少得多。其公共接口暴露任何属性,只有注册RegisterAttached静态方法,没有过载。
      公共类的DependencyProperty   {   / /字段   公共静态只读对象 UnsetValue;   / /方法   公共 PropertyMetadata使用getMetaData(类型forType);   name, Type propertyType, Type ownerType, PropertyMetadata typeMetadata); 公共静态的DependencyProperty注册( 字符串的名称,类型propertyType,类型ownerType,PropertyMetadata typeMetadata);   name, Type propertyType, Type ownerType, PropertyMetadata defaultMetadata); 公共静态的DependencyProperty RegisterAttached( 字符串名称,类型propertyType,ownerType类型,PropertyMetadata defaultMetadata);   } 

  • PropertyMetadata :其公共接口暴露任何属性,具有唯一的构造函数 ,默认值,PropertyChangedCallback,但不CoerceValueCallback。
      公共类 PropertyMetadata   {   / /方法   defaultValue); 公共 PropertyMetadata( 对象的DefaultValue);   公共 PropertyMetadata(PropertyChangedCallback propertyChangedCallback);   defaultValue, PropertyChangedCallback propertyChangedCallback); 公共 PropertyMetadata( 对象的DefaultValue,PropertyChangedCallback propertyChangedCallback);   / /属性   公共对象的DefaultValue {;}   } 

  • DependencyObject的 :它的公共接口的GetValue , 的SetValue , ReadLocalValue , ClearValue方法,但不是CoerceValue方法。
      DependencyObject的公共抽象类 :IManagedPeer,INativeCoreTypeWrapper   {   / /方法   保护 DependencyObject的();   [EditorBrowsable(EditorBrowsableState.Never)]   公共BOOL CheckAccess中();   公共无效 ClearValue(DependencyProperty的DP);   公共对象 GetAnimationBaseValue(DependencyProperty的DP);   公共对象的GetValue(DependencyProperty的DP);   公共对象 ReadLocalValue(DependencyProperty的DP);   ); 公共无效的SetValue(DependencyProperty的DP, 对象的值 );   / /属性   [EditorBrowsable(EditorBrowsableState.Advanced)]   公共分派分派{;}   } 

  • DependencyProperty.Register的方法:请注意,它并没有采取ValidateValueCallback参数。

    DependencyProperty.Register

  • PropertyMetadata构造方法:请注意,它并没有采取CoerceValueCallback参数。

    PropertyMetadata.PropertyMetadata

范例

概述

这是同一个例子,在第I部,但在Si​​lverlight上重新实现。 它有一个简单的类myB​​utton的继承按钮,并增加了一个依赖项属性MyValue。MyValue属性值必须是0和10之间,其有效价值是其IsEnabled从基类继承的财产的影响:如果IsEnabled是真实的,MyValue必须小于或等于5,O / W,它必须大于或等于6。

由于MyValue是一个依赖项属性,它应该有一个依赖项属性的所有的好处:

  • 它具有简单的CLR属性接口;
  • 它有一个默认值;
  • 其价值可以通过XAML代码,数据绑定,样式,动画等;
  • 动态决定它的价值是由它的依赖,并可以自动重新计算时,其依赖关系的变化;
  • 它通常具有为客户价值的改变和价值的事件改变了保护子类重写虚方法,以堵塞;
  • MyValue设置一个非法的值应该抛出一个ArgumentException,没有改变MyValue财产的价值或解雇其值更改事件;

实施模式

MyValue在执行下面的源代码如下常见的模式在Silverlight依赖项属性和实现/提供上述的好处所有的依赖项属性。 由于Silverlight属性系统只支持WPF属性系统功能的一个子集,特别是它不仅具有改变回调,但不直接支持验证和强制实施模式,依赖于Silverlight的财产实际上是非常棘手的,它是很容易产生微妙的错误,如果不小心,调试/节稍后尝试在这个岗位所示。

  • ; set ; } CLR包装: 公共INT MyValue {;;}
  • 相依性属性识别: 公共静态只读的DependencyProperty MyValueProperty
  • 产权制度的登记:DependencyProperty.Register的()
  • PropertyChangedCallback功能,是所有的DP功能(验证,胁迫,事件)的关键:
    • 私有静态无效 OnMyValuePropertyChanged(DependencyObject的D,DependencyPropertyChangedEventArgs E):PropertyChangedCallback功能
    • 私人INT _initialMyValu

      E:地方国有记得在根级别的PropertyChangedCallback MyValue属性以前的值,以避免不必要的/假的变化notfication

    • 私人INT _requestedMyValue:地方国有记得原来的用户要求设置为胁迫基地
    • 私人INT _nestLevel:递归调用的PropertyChangedCallback水平,为验证及强制执行,并防止从可见光到客户端的内部转换不发射假更改通知
  • 验证逻辑:
    • 私有静态布尔 IsValidMyValue(DependencyPropertyChangedEventArgs E):比赛WPF的ValicateValueCallback
    • 私有静态无效 ValidationHelper:一个共同的事业,恢复无效的变化,并抛出在验证失败情况下的例外
  • 胁迫的逻辑:
    • ): match WPF's CoerceValueCallback 私有静态对象 CoerceMyValue(DependencyObject的D,对象的值 ):比赛WPF的CoerceValueCallback
    • sender, DependencyPropertyChangedEventArgs e): to trigger automatic re-calculation of the effective value of MyValue property when its dependency IsEnabled changes.私有静态无效 OnIsEnabledChanged( 对象发件人,DependencyPropertyChangedEventArgs发送):触发自动重新计算的有效价值MyValue财产时,其依赖IsEnabled变化。
  • 事件
    • > MyValueChanged; 公共事件 RoutedPropertyChangedEventHandler <诠释 > MyValueChanged;
    • oldValue, int newValue) 受保护的虚拟无效OnMyValueChanged(INT oldValue,INT newValue)
    • 私有静态无效 OnMyValuePropertyChanged(DependencyObject的D,DependencyPropertyChangedEventArgs发送),CoerceMyValue静态方法

    您可能需要阅读的源代码,调试和实验一节中体会到如何在Silverlight相依性属​​性的正确实施的复杂性和美味,通过,在这里犯了一个错误,因为它真的很容易,Silverlight中的错误证明。

源代码

  • Page.xaml中:
      x:Class ="SLApp1.Page" <UserControl X:=“SLApp1.Page     XMLNS =“http://schemas.microsoft.com/winfx/2006/xaml/presentation”     的xmlns:X =“http://schemas.microsoft.com/winfx/2006/xaml”     XMLNS:我 =“CLR命名空间:SLApp1”     Height ="300" > WIDTH =“400”  =“300”>     x:Name ="LayoutRoot" Background ="White" > < 格X: 名称 =“LayoutRoot的” 背景 “白”>         x:Name ="mybtn" Content ="MyButton" Click ="mybtn_Click" < 我:myButton的 x:名称 =“mybtn” 内容 =“myButton的” 点击 “mybtn_Click”                      MyValueChanged =“mybtn_MyValueChanged”/>     > </  > > </ UserControl的 > 

  • page.xaml.cs:
     System.Windows; using System.Windows.Controls; namespace SLApp1 { // exampl to demonstrate how to implement dependency property on Silverlight public class MyButton : Button { // DP: CLR wrapper public int MyValue { get { return ( int )GetValue(MyValueProperty); } set { SetValue(MyValueProperty, value ); } } // DP: dependency property identifier & registration public static readonly DependencyProperty MyValueProperty = 使用系统; 使用 System.Windows; 使用 System.Windows.Controls 命名空间 SLApp1 {/ / exampl演示如何实现在Silverlight 公共类 myButton的依赖项属性 :按钮{/ / DP:CLR包装 公众诠释 MyValue {{( INT)的GetValue(MyValueProperty);} {的SetValue(MyValueProperty, 价值 );}} / / DP:依赖项属性标识符注册的 公共静态只读的DependencyProperty MyValueProperty =  IsValidMyValue(DependencyPropertyChangedEventArgs e) { int newValue = ( int )e.NewValue; return newValue >= 0 && newValue <= 10; } // DP: coercion callback private static object CoerceMyValue(DependencyObject d, object value ) { MyButton ctrl = (MyButton)d; int newValue = ( int ) value ; return ctrl.IsEnabled ? DP:验证回调 私有静态布尔 IsValidMyValue(DependencyPropertyChangedEventArgs E){newValue =(INT)e.NewValue;返回 newValue> = 0&&newValue <= 10;} / / DP:胁迫回调 私有静态对象 CoerceMyValue(DependencyObject的D, 对象值 ){myButton的CTRL =(myButton的)D; newValue =(int) ; 返回 ctrl.IsEnabled?  ValidationHelper( DependencyObject d, DependencyPropertyChangedEventArgs e, Predicate<DependencyPropertyChangedEventArgs> p) { if (!p(e)) { // Isolate SetValue call with _netLevel to prevent state change ((MyButton)d)._nestLevel++; d.SetValue(e.Property, e.OldValue); ((MyButton)d)._nestLevel--; throw new ArgumentException( "Invalid DP value" , "e" ); } } // DP: changed callback private static void OnMyValuePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { // validation first: in case of failure, revert change, // throw ArgumentException, no state change or changed notification ValidationHelper(d, e, IsValidMyValue); MyButton ctrl = (MyButton)d; int oldValue = ( int )e.OldValue; int newValue = ( int )e.NewValue; if (ctrl._nestLevel == 0) { // remember initial state ctrl._initialMyValue = oldValue; ctrl._requestedMyValue = newValue; } ctrl._nestLevel++; // coercion, DP stores effective value on SL int coercedValue = ( int )CoerceMyValue(d, e.NewValue); if (newValue != coercedValue) ctrl.MyValue = coercedValue; ctrl._nestLevel--; if (ctrl._nestLevel == 0 && ctrl.MyValue != ctrl._initialMyValue) { // changed notification happens only at root level (_nestLevel == 1) // and when there is a really a change (MyValue != _initialMyValue) ctrl.OnMyValueChanged(oldValue, ctrl.MyValue); } } // RE: use direct event to simulate routed event public event RoutedPropertyChangedEventHandler< int > MyValueChanged; // RE: provide a protected virtual for subclass to override protected virtual void OnMyValueChanged( int oldValue, int newValue) { RoutedPropertyChangedEventArgs< int > e = new RoutedPropertyChangedEventArgs< int >(oldValue, newValue); if (MyValueChanged != null ) MyValueChanged( this , e); } private int _initialMyValue; private int _requestedMyValue; private int _nestLevel; // DP: event handler to trigger re-calculation of DP because of dependency change private static void OnIsEnabledChanged( object sender, DependencyPropertyChangedEventArgs e) { MyButton ctrl = (MyButton)sender; // coerce local value to re-calculate effective value // set DP only when effective value changes to avoid blow away binding unnecessarily ctrl._nestLevel++; int oldValue = ctrl.MyValue; int newValue = ( int )CoerceMyValue(ctrl, ctrl._requestedMyValue); if (newValue != ctrl.MyValue) { ctrl.MyValue = newValue; ctrl.OnMyValueChanged(oldValue, ctrl.MyValue); } ctrl._nestLevel--; } public MyButton() { _initialMyValue = _requestedMyValue = MyValue; // init state IsEnabledChanged += OnIsEnabledChanged; // hook up dependency } } public partial class Page : UserControl { public Page() { InitializeComponent(); } private void mybtn_Click( object sender, RoutedEventArgs e) { } private void mybtn_MyValueChanged( object sender, RoutedPropertyChangedEventArgs< int > e) { int oldValue = e.OldValue; int newValue = e.NewValue; } } } Math.Min(5,newValue):Math.Max(6,newValue);} / / DP:常见的验证帮助/ /恢复的价值,并抛出异常在验证 失败的私有静态无效ValidationHelper(DependencyObject的D,DependencyPropertyChangedEventArgs E,谓词情况下<DependencyPropertyChangedEventArgs> p)){/ /隔离与_netLevel的SetValue调用,以防止状态的变化((myButton的)D)_nestLevel +(P(E); d.SetValue(e.Property,e.OldValue)( ( myButton的)D)_nestLevel - 抛出新ArgumentException(“无效的DP值”,“E”);}} / / DP:改变回调 私有静态无效 OnMyValuePropertyChanged(DependencyObject的D,DependencyPropertyChangedEventArgs E){/ /验证:失败的情况下,恢复改变,/ /抛出ArgumentException的,无状态的改变或改变 ValidationHelper 通知 (D,E,IsValidMyValue); myButton的CTRL =(myButton的)D; oldValue =(INT)e.OldValue; newValue =(INT )e.NewValue; 如果 (ctrl._nestLevel == 0){/ /记住初始状态 ctrl._initialMyValue = oldValue; ctrl._requestedMyValue = newValue;} ctrl._nestLevel + +; / /胁迫,DP的商店SL INT coercedValue 有效的价值 = (INT)CoerceMyValue(D,e.NewValue);如果 (newValue = coercedValue!)ctrl.MyValue = coercedValue; ctrl._nestLevel - ; 如果 (!ctrl._nestLevel == 0&&ctrl.MyValue = ctrl._initialMyValue){ / /改变通知只发生在根级别(_nestLevel == 1)/ /时,有一个真正的改变(!MyValue = _initialMyValue)ctrl.OnMyValueChanged(oldValue,ctrl.MyValue);}} / /可再生能源:直接使用事件模拟路由事件 公共事件 RoutedPropertyChangedEventHandler <INT> MyValueChanged; / /重新提供一个受保护的虚拟子类重写 受保护的虚拟无效OnMyValueChanged(INT oldValue,newValue){RoutedPropertyChangedEventArgs <INT> E =  RoutedPropertyChangedEventArgs < 诠释 >(oldValue的newValue);(MyValueChanged = NULL)MyValueChanged(E);} INT私人 _initialMyValue; 私人诠释 _requestedMyValue; 私人诠释 _nestLevel; / / DP的:事件处理程序,因为依赖变化触发重新计算的DP 私有静态 OnIsEnabledChanged( 对象发件人,DependencyPropertyChangedEventArgs发送){myButton的CTRL =(myButton的)发件人/ /强制本地值 无效 ,重新计算有效的价值/ /设置DP只有当有效的价值变动,以避免吹走约束力不必要ctrl._nestLevel + + INT oldValue = ctrl.MyValue; newValue =(INT)CoerceMyValue(CTRL,ctrl._requestedMyValue);如果 (newValue = ctrl.MyValue!){ctrl.MyValue = newValue; ctrl.OnMyValueChanged(oldValue,ctrl.MyValue);} CTRL。 _nestLevel - ;} myButton的公共 (){_initialMyValue = _requestedMyValue = MyValue; / /初始化状态 IsEnabledChanged + = OnIsEnabledChanged; 勾了依赖/ /}} 公共部分类页:UserControl的{ 公共页面(){的InitializeComponent();} 私人无效 mybtn_Click( 对象发件人,发送RoutedEventArgs){} 私人无效 mybtn_MyValueChanged( 对象发件人,RoutedPropertyChangedEventArgs <INT> E){INT oldValue = e.OldValue INT newValue = e.NewValue;}} 

调试和试验:依赖项属性如何在Silverlight工程

我在第一部分,我将演示如何依赖项属性的Silverlight调试和试验工作。 我设置断点,在最上面的源代码的功能从Visual Studio内启动的应用程序,点击打入mybtn_Click功能的按钮,然后检查国家和从Visual Studio的即时窗口内做实验。

默认值,有效值

首先,让我们检查后SLApp1休息到mybtn_Click功能的mybtn状态:

default value as effective value

  • mybtn.MyValue和mybtn.GetValue返回0,MyValue DP(DP = DependencyProperty的)的默认值。
  • mybtn.ReadLocalValue(MyButton.MyValueProperty)返回DependencyObject.UnsetValue,说明有此DP在mybtn没有本地值。因此,它是Silverlight返回DP的默认值作为其有效价值的产权制度。
  • mybtn.ClearVa​​lue(MyButton.MyValueProperty)没有任何效果,因为没有本地值清除。
  • 已初始化状态变量(_initialMyValue,_requestedMyValue)的有效价值MyValue myButton的构造函数。

验证

现在,让我们的实验验证。 键入mybtn.MyValue = -1在即​​时窗口:

validation

  • VS分成OnMyValuePropertyChanged PropertyChangedCallback静态方法,改变回调,因为所有的Silverlight属性系统支持。
  • mybtn输出,mybtn.MyValue,mybtn.GetValue(MyButton.MyValueProperty)表明MyValue,已经采取了非法的值-1,为地方和有效的价值,所以它处于无效状态。
  • 本地窗口显示e.Property类型CustomDependencyProperty。 在Silverlight上有许多细微的CoreDependencyProperty和CustomDependencyProperty之间的差异,因此有关WPF DependencyProperty的许多假设可能无法在Silverlight的真实。准备尝试和错误。
  • 为了模拟WPF的行为,OnMyValuePropertyChanged呼吁ValidationHelper首先验证e.NewValue,并恢复在验证失败情况下的变化,而引发不必要的变更通知为非法的新值-1。

validation

  • 看看调用堆栈窗口和源代码窗口上面:ValidationHelper调用IsValidMyValue,将返回-1 e.NewValue虚假。

validate & revert

  • 由于IsValidMyValue(参数p通过)返回false,如上图所示,ValidationHelper恢复DP值回e.OldValue变化。的SetValue调用不幸的是,这将触发一轮又一轮,甚至两轮的处理(验证/强制/更改的通知)改变递归,,即使它仍然是在当前DP值的中间改变处理,只是恢复的变化,不应该有发生开始递归是所有的复杂性,从 ​​在Silverlight相依性属性的正确实施。
  • “的SetValue调用方括号/保护一双_nestLevell + + / _nestLevell的报表时OnMyValuePropertyChanged是所谓再次递归,_nestLevel将可超过1,所以它知道它在递归,和会不会触发更改通知:在这种情况下从0到-1和-1至0,因为这些变化都将发生在WPF,并应听MyValueChanged事件到客户端只和不可见的内部。
  • 下面的屏幕截图显示OnMyValidationPropertyChanged是递归调用,而通过在上面的屏幕截图上线49条的SetValue加强:

validate, revert & recursion

  • 在屏幕截图,OnMyValuePropertyChanged显示了两次调用堆栈窗口,我们MyValue.set(-1)调用内部(和“评价:mybtn.MyValue = -1”从即时窗口)。
  • 在即时窗口中的输出显示,MyValue财产的价值是现在恢复从-1回来到0。
  • ((myButton的)D)。GetValue的(MyButton.MyValueProperty)输出为0,而不是对DependencyProperty.UnsetValue,表明mybtn现在有一个当地的价值,为此DP从DP登记,而不是采取默认值。
  • _nestLevel是1而不是0,因为OnMyValidationPropertyChanged被称为递归。
  • 在当地人的窗口,我们可以看到,E的NewValue和OldValue交换。 e.NewValue现在是0和有效的,所以ValidationHelper不会触发另一轮的变化处理。
  • 由于_nestLevel值1,所以如果从68至72条将不被执行,即,递归将不会改变本地状态(_initialMyValue和_requestedMyValue)。

validate, revert & recursion

  • 如上图所示,继续执行76行强制。 因为mybtn.IsEnabled是真实的,newValue是0,所以没有胁迫的情况下,是跳过78行,而不是造成另一轮因胁迫递归。
  • _netstLevel将81行,ctrl.MyValue等于ctrl._initialMyValue,所以从行更改的通知82至86条第,将被跳过了。OnMyValuePropertyChanged将返回,调用栈回溯到ValidationHelper呼叫,如下所示。

exception for validation failure

  • 回到ValidationHelper,恢复旧值后,ValidationHelper抛出ArgumentExeption为无效的新的价值,而这一切是在不改变状态(_initialMyValue和_requestedMyValue)或触发改变的通知(在这种情况下,从0到-1 -1为0)。

强迫

现在,让我们的实验与胁迫:mybtn.MyValue设置到8触发胁迫,mybtn.MyValue应该最终为5而不是8因为IsEnabled是真实的,MyValueChanged事件应与发射新的价值5。自8是一个有效的值,应该记住;时的依赖IsEnabled变化,MyValue的有效价值的重新的计算应该发生,并应改变MyValue的有效价值的最初requeste和现在有效的价值8,和MyValueChanged事件应与发射新的价值8。

如下图所示,mybtn.MyValue = 8在即时窗口触发OnMyValuePropertyChanged静态方法,因为在以前,但有一些不同的情况下mybtn.MyValue = -1:

coercion

  • 在上面的屏幕截图,8 e.NewValue IsValidMyValue验证,所以没有的SetValue调用和递归内ValidationHelper改变处理。
  • 因为这是改变处理的根致电(_nestLevel值为0 OnMyValuePropertyChanged的),如果执行从行的第68至72,要记住的状态,如在即时窗口CTRL输出显示。
  • 继续执行行胁迫76。

coercion causes recursive changed handling

  • 在屏幕截图CoerceMyValue返回5,有效的价值,因为IsEnabled是真实的,所要求的新的价值是8。
  • 有效值为5,这将触发OnMyValuePropertyChanged,IsValidMyValue MyValue OnMyValuePropertyChanged套,CoerceMyValue等递归调用再次值为5。自5是有效的,已经裹挟,将继续坚持。

change notification

  • 如上图所示,执行回来胁迫,mybtn(CTRL),作为其有效和地方MyValue的DP值,但还记得8 _requestedMyValue领域所要求的值。
  • 更改的通知只发生在通话的根级别(_nestLevel 0)时,确实是一个有效的DP值的变化(MyValue = _initialValue) 。
  • MyValueChanged事件总是触发新的有效的值(ctrl.MyValue,coercedValue,ctrl.ReadLocalValue()都应该在新的有效的值)。
  • 下面的屏幕截图显示事件处理调用堆栈:

changed event firing & handling

动态重新计算的相依性的有效价值

现在,让我们的实验与动态/自动重新计算相依性属性的依赖项更改时,其有效价值。

类型mybtn.IsEnabled = FALSE在即时窗口:

dynamic/automatic effective value

  • IsEnabled变化是异步处理 ,即改变IsEnabled不会导致其处理程序OnIsEnabledChanged立即调用。你必须立即按F5让SLApp1运行,因此它可以拿起IsEnabledChanged事件,并打入OnIsEnabledChanged如果等待几秒钟,然后按F5,IsEnabled更改事件将永远消失,并OnIsEnabledChanged将不会被调用。尽管事件处理是异步的,可能会丢失,变化的影响是同步的,棒:现在被禁用按钮。 所以如果你不迅速打在mybtn.IsEnabled打字后F5 =假的,你将能够继续进行实验,因为按钮现在被禁用,将不响应点击,所以你将不得不重新启动程序继续进行实验。短调用堆栈的asynchronousness还显示,自“mybtn.IsEnabled = FALSE”立即返回,并在立即窗口中打印出虚假的,和调用堆栈不包含像行“的评价:mybtn.IsEnabled = FALSE”,在“评价的情况下:mybtn.MyValue = 8”,在先前的实验异步和瞬态事件的处理可能是一个良好的性能和可靠性的提高,但它也使事情变得非常棘手,所以请记住的异步性质!
  • 产权制度不知道的依赖关系取决于一个DP上,使开发人员提供类似处理的IsEnabledChanged事件触发的例子MyValue重新计算的逻辑,。
  • 请注意,我们强迫缓存_requestedMyValue,不ctrl.MyValue,现行有效的价值。 有效的价值不应该被胁迫的基础,并可能不再有效的依赖改变。
  • 方括号内OnIsEnabledChanged的代码是/一双_nestLevel + + / _nestLevel陈述保护,防止其递归代码和状态改变(_initialMyValue _requestedMyValue)。副作用是没有MyValueChanged事件将被解雇,所以OnIsEnabledChanged已明确火灾事件时,有的确是一个有效的值的变化。

做最后的实验是在即时窗口中调用mybtn.ClearVa​​lue(MyButton.MyValidProperty),这将引发OnMyValuePropertyChanged称为新值0,默认值作为新的有效的价值,因为本地值8,现在被清除:

ClearValue causes re-calculation of effective value and change notification

新的有效值为0将强制通过递归调用的OnMyValuePropertyChanged(两次OnMyValuePropertyChanged显示在下面的调用堆栈窗口)6,因为IsEnabled仍然是假的。最终mybtn.MyValue将安身立命的有效和地方价值6,并MyValueChanged事件是发射新的价值6。

Coersion and final change notification

结论

,因为Silverlight只支持PropertyValueChangedCallback,实施验证,并胁迫在Silverlight可以非常棘手,因为验证和胁迫逻辑只能通过PropertyValueChangedCallback实施,如果验证或胁迫的变化有效的DP值,PropertyValueChangedCallback可以递归调用,这大大复杂的逻辑。加Silverlight的不记得最初请求的DP稍后胁迫的价值,并不允许DP将处于无效状态,所以有很多地方在实施有关​​Silverlight相依性属​​性的错误。

这是另一个长的职位。 如果有足够的兴趣,我可以看一下提供的代码片段和一些辅助类来实现的实施在Silverlight相依性属​​性,WPF和Silverlight产权制度之间的差异最小化的基本水暖,使贯彻落实SL那样简单的DP在WPF。

的标签: Silverlight,Silverlight工具包,依赖项属性, Coersion,验证

http://www.ningzhang.org/zh-CN/2008/11/11/dependencyproperty-validation-coercion-change-handling-part-ii-silverlight/

原创粉丝点击