[WPF] Chapter XII property validation study

  When you define any type of property, you have to face the possibility of errors set properties. For conventional .NET attributes, such problems may attempt to acquire the property setter. But for purposes of dependency properties, this method is not suitable because () method may be used directly SetValue properties by the WPF property system.

  Instead, WPF provides two ways to stop illegal value:

  • A ValidateValueCallback : The callback function may accept or reject the new value. In general, obvious errors in violation of the constraint attribute callback function for capturing. The callback function can be provided as a parameter to the method DependencyProperty.Register ().
  • A CoerceValueCallback : The callback function can be modified to new values more acceptable value. The callback function is typically used to handle conflicting dependency attribute values set for the same subject. These values themselves may be legitimate, but at the same time when applications are incompatible. To use this callback function when creating FrameworkPropertyMetadata object (the object is then passed to DependencyProperty.Register () method), as a parameter to the constructor provides the callback function.

  Here is when an application tries to set dependency properties, role in the process of all these elements:

  (1) First, CoerceValueCallback method has the opportunity to modify the value provided (generally, the value of property and other offers compatibility), or return DependencyProperty.UnsetValue, which would completely reject changes.

  (2) Next ValidateValueCallback activation method. The method returns true value to accept as a valid value, or returns false rejection value. CoerceValueCallback with different methods, ValidateValueCallback access methods can not set the actual object properties, which means that you can not check the values ​​of other attributes.

  (3) Finally, if the first two phases are successful, it will trigger PropertyChangedCallback method. At this point, if you want to provide notice to other classes, it can lead to change events.

First, verify callback

  As previously seen, DependencyProperty.Register () method takes an optional validation callback:

static FrameworkElement(){
    FrameworkPropertyMetadata metadata=new FrameworkPropertyMetadata(new Thickness(),FrameworkPropertyMetadataOptions.AffectsMeasure);

    MarginProperty=DependencyProperty.Register("Margin",typeof(Thickness),typeof(FrameworkElement),metadata,new ValidateValueCallback(FrameworkElement.IsMarginValid));
    ....
}

  The callback function can be used to verify, verification should generally be added to the process set some properties. The callback function must provide a point to accept the object parameter and returns a Boolean worth method. Returns true target is legal to accept and false reject object.

  Verification of the properties FrameworkElement.Margin very tedious, because it relies on the inside of Thickness.IsValid () method. This approach ensures Thickness objects currently in use (expressed margin) is legal. For example, a subject may be constructed Thickness perfectly acceptable (but is not suitable for setting margins). One example is the Thickness object using a negative value. If the Thickness object provides for the margins are not legitimate. IsMarginValid method returns false:

public static bool IsMarginValid(object value)
{
    Thickness thickness1=(Thickness)value;
    return thickness1.IsValid(true,false,true,false);
}

  There is a limit to verify the callback function: they must be static and do not have access method being validated object. All information can be obtained only value just applied. Despite this easier to reuse the property, but may not create validation routines to consider other attributes. A typical example is an element having properties Minimum and Maximum. Obviously, the attribute value is set to not less than the Maximum value for the Minimum property. However, you can not use a callback function to verify the implementation of this logic, because once you visit a property grace.

Second, mandatory callback

  CoerceValueCallback callback function by using FrameworkPropertyMetadata object. Here is an example:

FrameworkPropertyMetadata metadata=new FrameworkPropertyMetadata(new Thickness(),FrameworkPropertyMetadataOptions.AffectsMeasure);
metadata.CoerceValueCallback=new CoerceValueCallback(CoerceMaximum);
DependencyProperty.Register("Maxium",typeof(double),typeof(RangeBase),metadata);

  Attribute associated with each may be processed by CoerceValueCallback callback function. For example, ScrollBar control provides Maximum, Minimum and Value properties, these properties are inherited from RangeBase class. A method of retaining these properties are used for adjusting the force attribute.

  For example, when setting Maximum property, force must be used to ensure that no less than the Minimum property values:

private static object CoerceMaximum(DependencyObject d,object value)
{
    RangeBase base1=(RangeBase)d;
    if((double)value)<base1.Minimum)
    {
        return base1.Minimum;
    }
    return value;
}

  In other words, if the applied Maximum Minimum property value is less than the value of the attribute, the attribute is set with the value Maximum Minimum property. Note that, CoerceValueCallback passing two parameters - the ready to use value and a value to be applied to get the object.

  When setting the Value property, a similar process occurs force. Value property of mandatory, to ensure that no departing from the scope defined by the Minimum and Maximum properties using the following code:

internal static object ConstrainToRange(DependencyObject d,object value)
{
    double newValue=(double)value;
    RangeBase base1=(RangeBase)d;
    double minimum=base1.Minimum;
    if(newValue<minimum)
    {
        return minimum;
    }
    double maximum=bas1.Maximum;
    if(newValue>maximum)
    {
        return maximum;
    }
    return newValue;
}

  Minimum property values ​​do not use coercion. On the contrary, once the value changes, triggered PropertyChangedCallback, and then manually trigger the enforcement process and Maximum Value property to enable them to adapt to changes in the Minimum property worth:

private static void OnMinimumChanged(DependencyObject d,DependencyPropertyChangedEventArgs e)
{
    RangeBase base1=(RangeBase)d;
    ...
    base1.CoerceValue(RangeBase.MaximumProperty);
    base1.CoerceValue(RangeBase.ValueProperty);
}

  Similarly, once set or enforce Maximum property value, then the Value property will be manually forced to adapt to changes in the Maximum property worth:

private static void OnMaximumChanged(DependencyObject d,DependencyPropertyChangedEventArgs e)
{
    RangeBase base1=(RangeBase)d;
    ...    
    base1.CoerceValue(RangeBase.ValueProperty);
    base1.OnMaximumChanged((double)e.OldValue,(double)e.NewValue);
}

  If the value is set to collide with each other, the end result is the Minimum property has priority, followed by the Maximum property (and may be forced to the Minimum property), and finally the Value property (and may be forced Maximum and Minimum properties).

 

Guess you like

Origin www.cnblogs.com/Peter-Luo/p/12232496.html