Jak ustawić powiązanie w kodzie?

98

Mam potrzebę ustawienia powiązania w kodzie.

Wydaje się, że nie mogę tego zrobić dobrze.

Oto, czego próbowałem:

XAML:

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

Kod za:

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

Właściwość nie aktualizuje się po jej ustawieniu.

Co ja robię źle?

Willem
źródło

Odpowiedzi:

196

Zastąpić:

myBinding.Source = ViewModel.SomeString;

z:

myBinding.Source = ViewModel;

Przykład:

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

Twoje źródło powinno być po prostu ViewModel, .SomeStringczęść jest obliczana z Path( Pathmoże być ustawiona przez konstruktora lub przez Pathwłaściwość).

Dyppl
źródło
14
Możesz także użyć txtText.SetBinding (TextBox.TextProperty, myBinding) zamiast ostatniej linii, aby ograniczyć pisanie :)
Manish Dubey
6
@ManishDubey Zaletą metody statycznej jest to, że pierwszy parametr jest zdefiniowany jako DependencyObject, dzięki czemu umożliwia powiązanie danych z obiektami, które nie pochodzą z FrameworkElement lub FrameworkContentElement (takich jak Freezables).
FreddyFlares,
Dzięki za to. Trochę się męczyłem, szukając takiego przykładu
Jesse Roper
12

Musisz zmienić źródło na obiekt viewmodel:

myBinding.Source = viewModelObject;
bartosz.lipinski
źródło
2

W uzupełnieniu do odpowiedzi z Dyppl , myślę, że byłoby miło, aby umieścić wewnątrz tego OnDataContextChangedwydarzenia:

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

Mieliśmy również przypadki, w których po prostu zapisaliśmy DataContextwłaściwość lokalną i wykorzystaliśmy ją do uzyskania dostępu do właściwości modelu widoku . Wybór oczywiście należy do Ciebie, podoba mi się to podejście, ponieważ jest bardziej spójne z resztą. Możesz również dodać weryfikację, na przykład sprawdzanie wartości null. Jeśli faktycznie zmienisz swoje miejsce DataContext, myślę, że fajnie byłoby również zadzwonić:

BindingOperations.ClearBinding(myText, TextBlock.TextProperty);

aby wyczyścić powiązanie starego modelu widoku ( e.oldValuew programie obsługi zdarzeń).

sommmen
źródło