سؤال

لدي عنصر تحكم باستخدام DependencyProperty مع CoerceValueCallback.ترتبط هذه الخاصية بخاصية موجودة في كائن نموذج.

عند ضبط خاصية التحكم على قيمة تسبب الإكراه، يقوم Binding بدفع القيمة غير مكره القيمة لكائن النموذج.يتم فرض قيمة الخاصية على عنصر التحكم بشكل صحيح.

كيف يمكنني الحصول على الرابط لدفع ملف بالإكراه القيمة لكائن النموذج؟

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;
        }
    }
}
هل كانت مفيدة؟

المحلول

لا أعتقد أن المقصود من رد الاتصال القسري هو أن يكون طريقًا ذو اتجاهين.أحد الحلول هو تحديث قيمة النموذج داخل رد الاتصال القسري.

نصائح أخرى

أعتقد أن هذه هي فكرة الإكراه بأكملها - القيمة الصحيحة بسرعة دون التسبب في تعديل أي تبعيات أخرى.يمكنك استخدام الكود أدناه بدلاً من آليات الإكراه الأصلية:

OnPChanged(/* ... */)
{
    // ...
    var coercedP = CoerceP(P);
    if (P != coercedP)
        P = coercedP;
    // ...
}

هث.

إليك طريقة التمديد حيث تقوم بتعيين القيمة على الكائن المستهدف

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;
    }
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top