如何在代码中设置绑定?

我需要在代码中设置绑定。

我似乎不能得到它的权利。

这就是我所尝试的:

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

视图模型:

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

当我设置该属性时,它没有更新。

我做错了什么?

119444 次浏览

Replace:

myBinding.Source = ViewModel.SomeString;

with:

myBinding.Source = ViewModel;

Example:

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

Your source should be just ViewModel, the .SomeString part is evaluated from the Path (the Path can be set by the constructor or by the Path property).

You need to change source to viewmodel object:

myBinding.Source = viewModelObject;

In addition to the answer of Dyppl, I think it would be nice to place this inside the OnDataContextChanged event:

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

We have also had cases were we just saved the DataContext to a local property and used that to access viewmodel properties. The choice is of course yours, I like this approach because it is more consistent with the rest. You can also add some validation, like null checks. If you actually change your DataContext around, I think it would be nice to also call:

BindingOperations.ClearBinding(myText, TextBlock.TextProperty);

to clear the binding of the old viewmodel (e.oldValue in the event handler).

Example:

DataContext:

  class ViewModel
{
public string SomeString
{
get => someString;
set
{
someString = value;
OnPropertyChanged(nameof(SomeString));
}
}
}

Create Binding:

  new Binding("SomeString")
{
Mode = BindingMode.TwoWay,
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
};