Como definir uma vinculação no código?


96

Tenho a necessidade de definir um enlace no código.

Parece que não consigo acertar.

Isso é o que eu tentei:

XAML:

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

Código por trá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");
      }
    }

A propriedade não está sendo atualizada quando a configuro.

O que estou fazendo de errado?

Respostas:


193

Substituir:

myBinding.Source = ViewModel.SomeString;

com:

myBinding.Source = ViewModel;

Exemplo:

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

Sua fonte deve ser justa ViewModel, a .SomeStringparte é avaliada a partir do Path(o Pathpode ser definido pelo construtor ou pela Pathpropriedade).


14
Você também pode usar txtText.SetBinding (TextBox.TextProperty, myBinding) no lugar da última linha apenas para reduzir a digitação :)
— Manish Dubey

5
@ManishDubey O benefício do método estático é que o primeiro parâmetro é definido como DependencyObject, portanto, permite a vinculação de dados em objetos que não derivam de FrameworkElement ou FrameworkContentElement (como Freezables).
— FreddyFlares

Obrigado por isso. Tive dificuldade em encontrar um exemplo como este
— Jesse Roper

11

Você precisa alterar a fonte para o objeto viewmodel:

myBinding.Source = viewModelObject;

1

Além da resposta do Dyppl , acho que seria bom colocar isso dentro do 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);
}

Também tivemos casos em que apenas salvamos o DataContextem uma propriedade local e usamos isso para acessar as propriedades do viewmodel. A escolha é naturalmente sua, gosto dessa abordagem porque é mais consistente com as demais. Você também pode adicionar alguma validação, como verificações de nulos. Se você realmente mudar de posição DataContext, acho que seria bom também chamar:

BindingOperations.ClearBinding(myText, TextBlock.TextProperty);

para limpar a vinculação do modelo de visão antigo ( e.oldValueno manipulador de eventos).

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.