¿Cómo establecer un enlace en el código?

97

Tengo la necesidad de establecer un enlace en el código.

Aunque parece que no puedo hacerlo bien.

Esto es lo que he probado:

XAML:

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

Código detrás:

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

La propiedad no se actualiza cuando la configuro.

¿Qué estoy haciendo mal?

Willem
fuente

Respuestas:

194

Reemplazar:

myBinding.Source = ViewModel.SomeString;

con:

myBinding.Source = ViewModel;

Ejemplo:

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

Su fuente debe ser justa ViewModel, la .SomeStringparte se evalúa desde el Path( Pathel constructor o la Pathpropiedad pueden establecerlo).

Dyppl
fuente
14
También puede usar txtText.SetBinding (TextBox.TextProperty, myBinding) en lugar de la última línea solo para reducir la escritura :)
Manish Dubey
5
@ManishDubey El beneficio del método estático es que el primer parámetro se define como DependencyObject, por lo que habilita el enlace de datos en objetos que no derivan de FrameworkElement o FrameworkContentElement (como Freezables).
FreddyFlares
Gracias por esto. Luché un poco buscando un ejemplo como este
Jesse Roper
12

Necesita cambiar la fuente al objeto viewmodel:

myBinding.Source = viewModelObject;
bartosz.lipinski
fuente
2

Además de la respuesta de Dyppl , creo que sería bueno colocar esto dentro del OnDataContextChangedevento:

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

También hemos tenido casos en los que simplemente guardamos el DataContextarchivo en una propiedad local y lo usamos para acceder a las propiedades del modelo de vista. La elección es, por supuesto, suya, me gusta este enfoque porque es más consistente con el resto. También puede agregar alguna validación, como verificaciones nulas. Si realmente cambia su DataContextentorno, creo que sería bueno llamar también:

BindingOperations.ClearBinding(myText, TextBlock.TextProperty);

para borrar el enlace del modelo de vista antiguo ( e.oldValueen el controlador de eventos).

sommmen
fuente