Как установить привязку в коде?

Мне нужно установить привязку в коде.

Я не могу понять, как это правильно.

Вот что я пробовал:

XAML:

<TextBox Name="txtText"></TextBox>

Код позади:

Binding myBinding = new Binding("SomeString");
myBinding.Source = ViewModel.SomeString;
myBinding.Mode = BindingMode.TwoWay;
myBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
BindingOperations.SetBinding(txtText, TextBox.TextProperty, myBinding);

ViewModel:

public string SomeString
    {
      get
      { 
          return someString;
      }
      set 
      { 
          someString= value;
          OnPropertyChanged("SomeString");
      }
    }

Свойство не обновляется, когда я его устанавливаю.

Что я делаю неправильно?

Ответ 1

Попробуйте следующее:

Binding myBinding = new Binding();
myBinding.Source = ViewModel;
myBinding.Path = new PropertyPath("SomeString");
myBinding.Mode = BindingMode.TwoWay;
myBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
BindingOperations.SetBinding(txtText, TextBox.TextProperty, myBinding);

Если вы укажете path (как вы делаете в конструкторе), ваш источник должен быть просто ViewModel, часть .SomeString оценивается по пути.

Ответ 2

вам нужно изменить источник на объект viewmodel:

myBinding.Source = viewModelObject;

Ответ 3

В дополнение к ответу Dyppl, я думаю, было бы неплохо поместить это в событие OnDataContextChanged:

private void OnDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
    // Unforunately we cannot bind from the viewmodel to the code behind so easily, the dependency property is not available in XAML. (for some reason).
    // To work around this, we create the binding once we get the viewmodel through the datacontext.
    var newViewModel = e.NewValue as MyViewModel;

    var executablePathBinding = new Binding
    {
        Source = newViewModel,
        Path = new PropertyPath(nameof(newViewModel.ExecutablePath))
    };

    BindingOperations.SetBinding(LayoutRoot, ExecutablePathProperty, executablePathBinding);
}

У нас также были случаи, когда мы просто сохраняли текст данных в локальном свойстве и использовали его для доступа к свойствам viewmodel. Выбор, конечно, за вами, мне нравится этот подход, потому что он более соответствует остальным. Вы также можете добавить некоторую проверку, например, нулевые проверки. Если вы на самом деле измените свой текстовый контекст, я думаю, было бы неплохо также вызвать BindingOperations.ClearBinding(myText, TextBlock.TextProperty);, чтобы очистить привязку старой модели представления (e.oldValue в обработчике событий).