2012-06-20 2 views
5

Можно ли установить значение за двусторонней привязкой напрямую, не зная связанного свойства?Прямо установить значение привязки

У меня есть вложенное свойство, которое связано со свойством, как это:

<Element my:Utils.MyProperty="{Binding Something}" /> 

Теперь я хочу, чтобы изменить значение, которое фактически хранящийся в Something с точки зрения вложенного свойства. Поэтому я не могу напрямую получить доступ к связанному свойству, но имеет только ссылки на DependencyObject (т. Е. Экземпляр элемента) и сам объект DependencyProperty.

Проблема при простой настройке через DependencyObject.SetValue заключается в том, что это эффективно удаляет привязку, но я хочу изменить основное свойство привязки.

Использование BindingOperations Я могу получить как Binding, так и BindingExpression. Теперь есть способ получить доступ к собственности за ней и изменить ее ценность?

+0

Вы писали Прилагаемый-проп себя как в вы можете изменить его PropertyMetadata? Наверное, нет? –

+0

@HellScream Да, я пишу собственность самостоятельно, поэтому я могу изменить метаданные, если это поможет. – poke

ответ

3

Хорошо, я решил это сейчас сам используя несколько рефлексивных трюков в выражении привязки.

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

BindingExpression bindingExpression = BindingOperations.GetBindingExpression(dependencyObj, dependencyProperty); 
if (bindingExpression != null) 
{ 
    PropertyInfo property = bindingExpression.DataItem.GetType().GetProperty(bindingExpression.ParentBinding.Path.Path); 
    if (property != null) 
     property.SetValue(bindingExpression.DataItem, newValue, null); 
} 
+0

он не работает, когда путь сложный. Потому что, когда путь - это что-то вроде Customer.Name, фактическое свойство не существует в DataItem BindingExpression. Он принадлежит другому объекту (в этом случае клиентом). –

+0

@ KubilayKara Если вы прочтете мой ответ, вы заметите, что я сказал, что он будет работать только для простых имен свойств. Если у вас есть сложные пути связывания, вам придется сначала проанализировать путь и пересечь объекты, чтобы найти правильное свойство. – poke

0

Как насчет того, чтобы наложить DependencyObjet на Element и установить свойство? Это возможно?

+0

Поскольку свойство является присоединенным свойством, тип элемента не содержит такого свойства. И 'Something' является частью контекста данных, с которым у меня нет прямого доступа, откуда я хочу изменить значение. – poke

0

Попробуйте установить значение по умолчанию в PropertyMetadata

Вы можете найти более подробную информацию о MSDN - http://msdn.microsoft.com/en-us/library/system.windows.propertymetadata.aspx

Вот пример:

public Boolean State 
    { 
    get { return (Boolean)this.GetValue(StateProperty); } 
    set { this.SetValue(StateProperty, value); } 
    } 
    public static readonly DependencyProperty StateProperty = DependencyProperty.Register(
    "State", typeof(Boolean), typeof(MyStateControl),new PropertyMetadata(myDefaultValue)); 
+0

Свойство уже имеет значение по умолчанию, но я хочу изменить значение * впоследствии *. Кроме того, я не думаю, что значение по умолчанию вообще считается, когда значение прикрепленного свойства действительно установлено (привязке). – poke

0

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

Это верно, если для параметра Binding.Mode установлено значение OneWay. Если он установлен на TwoWay, использование DependencyObject.SetValue не удалит привязку.

Это цитата из Pro WPF 4.5 в C# (страница 232):

Удаление привязки: Если вы хотите, чтобы удалить связывание, так что вы можете установить свойство в обычном порядке, вы нужна помощь метода ClearBinding() или ClearAllBindings(). Недостаточно просто применить новое значение к свойству. Если вы используете двустороннюю привязку, значение, которое вы установили, распространяется на связанный объект, и оба свойства остаются синхронизированными.

Итак, чтобы иметь возможность изменять (и распространять) мои: Утилиты.MyProperty с SetValue без удаления привязки:

<Element my:Utils.MyProperty="{Binding Something, Mode=TwoWay}" /> 
0

Вы можете передать значение через привязку к фиктивному объекту.

public static void SetValue(BindingExpression exp, object value) 
    { 
     if (exp == null) 
      throw new ValueCannotBeNullException(() => exp); 
     Binding dummyBinding = new Binding(exp.ParentBinding.Path.Path); 
     dummyBinding.Mode = BindingMode.OneWayToSource; 
     dummyBinding.Source = exp.DataItem; 
     SetValue(dummyBinding, value); 
    } 

    public static void SetValue(Binding binding, object value) 
    { 
     BindingDummyObject o = new BindingDummyObject(); 
     BindingOperations.SetBinding(o, BindingDummyObject.ValueProperty, binding); 
     o.Value = value; 
     BindingOperations.ClearBinding(o, BindingDummyObject.ValueProperty); 
    } 

Это мой фиктивный объект

internal class BindingDummyObject : DependencyObject 
{ 
    public object Value 
    { 
     get 
     { 
      return (object)GetValue(ValueProperty); 
     } 
     set 
     { 
      SetValue(ValueProperty, value); 
     } 
    } 

    public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(object), typeof(BindingDummyObject)); 
} 
Смежные вопросы