如何使 Binding 尊重 DependencyProperty 值强制?

Posted

技术标签:

【中文标题】如何使 Binding 尊重 DependencyProperty 值强制?【英文标题】:How do I make Binding respect DependencyProperty value coercion? 【发布时间】:2010-10-05 16:44:39 【问题描述】:

我有一个带有 CoerceValueCallback 的 DependencyProperty 控件。 此属性绑定到模型对象的属性。

当将控件属性设置为导致强制的值时,Binding 会将 uncoerced 值推送到模型对象。控件上的属性值被正确强制。

如何让 Binding 将 coerced 值推送到模型对象?

void Initialize()

    UIObject ui = new UIObject();
    ModelObject m = new ModelObject();
    m.P = 4;

    Binding b = new Binding("P");
    b.Source = m;
    b.Mode = BindingMode.TwoWay;
    Debug.WriteLine("SetBinding");
    // setting the binding will push the model value to the UI
    ui.SetBinding(UIObject.PProperty, b);

    // Setting the UI value will result in coercion but only in the UI.
    // The value pushed to the model through the binding is not coerced.
    Debug.WriteLine("Set to -4");
    ui.P = -4;

    Debug.Assert(ui.P == 0);
    // The binding is TwoWay, the DP value is coerced to 0.
    Debug.Assert(m.P == 0); // Not true. This will be -4. Why???


class UIObject : FrameworkElement

    public static readonly DependencyProperty PProperty =
        DependencyProperty.Register("P", typeof(int), typeof(UIObject), 
        new FrameworkPropertyMetadata(
            new PropertyChangedCallback(OnPChanged), 
            new CoerceValueCallback(CoerceP)));

    public int P
    
        get  return (int)GetValue(PProperty); 
        set  SetValue(PProperty, value); 
    

    private static void OnPChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    
        Debug.WriteLine(typeof(UIObject) + ".P changed from " + e.OldValue + " to " + e.NewValue);
    

    private static object CoerceP(DependencyObject sender, object value)
    
        int p = (int)value;
        if (p < 0)
        
            Debug.WriteLine(typeof(UIObject) + ".P coerced from " + p + " to 0");
            p = 0;
        
        return p;
    


class ModelObject

    private int p;
    public int P
    
        get
        
            Debug.WriteLine(this + ".P returned " + this.p);
            return this.p;
        
        set
        
            Debug.WriteLine(this + ".P changed from +" + this.p + " to " + value);
            this.p = value;
        
    

【问题讨论】:

【参考方案1】:

我认为这就是强制转换的全部想法 - 即时正确的值,而不会触发对任何其他依赖项的修改。您可以使用下面的代码代替原生强制机制:

OnPChanged(/* ... */)

    // ...
    var coercedP = CoerceP(P);
    if (P != coercedP)
        P = coercedP;
    // ...

HTH。

【讨论】:

我有点困惑..你为什么要强制一个值但仍然有例如绑定到属性的 GUI 元素显示非强制值? GUI 然后会显示一些不真实的东西...... 的想法是,如果您在绑定的两侧强制执行,那么绑定的 GUI 或绑定的任何内容都不会出现问题。 Topicstarter 正在尝试强制接收端的值(例如在 GUI 端)。【参考方案2】:

我不认为强制回调是双向的。一种解决方法是在强制回调中更新模型的值。

【讨论】:

【参考方案3】:

这是在目标对象上设置值的扩展方法

public static void SetTargetValue<T>(this FrameworkElement element, DependencyProperty dp, T value)
    
        var binding = BindingOperations.GetBinding(element, dp);
        if (binding == null) return;
        var name = binding.Path.Path;
        var splits = name.Split('.');
        var target = element.DataContext;
        for (var i = 0; i < splits.Length; i++)
        
            PropertyInfo property;
            if (i == splits.Length - 1)
            
                property = target.GetType().GetProperty(splits[i]);
                property.SetValue(target, value);
            
            else
            
                property = target.GetType().GetProperty(splits[i]);
                target = property.GetValue(target);
            
        
    

因此,在此方法中,使用绑定,您可以将值设置为源。当然源路径可以有很多名称 - Property1.Property2.Property3 等。 在强制方法中你只需要调用这个方法:

private static object CoerceProperty(DependencyObject d, object baseValue)
    
        if (!Check)
        
            var sender = (FrameworkElement)d;
            sender.SetTargetValue(MyPropertyProperty, myValue);
            return needValue;
        
        return baseValue;
    

【讨论】:

以上是关于如何使 Binding 尊重 DependencyProperty 值强制?的主要内容,如果未能解决你的问题,请参考以下文章

如何使 ls 尊重 .hidden 文件?

如何使 NSExpression 的 expressionForFunction:withArguments: 尊重获取请求的谓词

Dependency Property 依赖属性

如何使 Visual Studio 自动格式化程序尊重 JSDoc 注释?

如何使故事板中的 UiView 尊重百分比[重复]

在行中包含大图像时,如何使 IE 11 尊重表格中的列宽?