2009-02-05 7 views
10

У меня есть элемент управления DependencyProperty с CoerceValueCallback. Это свойство привязано к объекту модели объекта.Как заставить привязку уважать зависимость отношения значения DependencyProperty?

При настройке свойства управления на значение, вызывающее принуждение, привязка нажимает на объект модели . Значение свойства на элементе управления принудительно выполняется.

Как получить привязку, чтобы нажимать значение для объекта модели?

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

Я не думаю, что обратный вызов coerce предназначен для двусторонней улицы. Одним из способов решения этой проблемы было бы обновление ценности модели внутри обратного вызова coerce.

2

Я думаю, что это вся идея принуждения - правильное значение «на лету», не вызывая изменения каких-либо других зависимостей. Вы можете использовать приведенный ниже код вместо собственных механизмов принуждения:

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

HTH.

+3

Я немного запутался .. почему вы хотите, чтобы принуждать значение, но по-прежнему имеет Элементы GUI, привязанные к свойству, отображают неизменяемое значение? Затем графический интерфейс отобразит что-то, что не соответствует действительности ... –

+0

Думаете, что если вы будете принуждать принуждение по обе стороны привязки, тогда не будет ничего плохого в связанном графическом интерфейсе или чем-то, на что он ограничен. Topicstarter пытается принудить стоимость на принимающей стороне (например, на стороне GUI). – archimed7592

0

Вот метод расширения, где вы установите значение на целевом объекте

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); 
      } 
     } 
    } 

Таким образом, в этом методе, с помощью связывания, вы можете установить значение источника. Из источника Cource Путь может иметь много имен - 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; 
    } 

 Смежные вопросы

  • Нет связанных вопросов^_^