Reputation: 9476
I have the need to set a binding in code.
I can't seem to get it right tho.
This is what i have tried:
XAML:
<TextBox Name="txtText"></TextBox>
Code behind:
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");
}
}
The property is not updating when i set it.
What am i doing wrong?
Upvotes: 113
Views: 131562
Reputation: 1559
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
};
Upvotes: 0
Reputation: 2667
You need to change source to viewmodel object:
myBinding.Source = viewModelObject;
Upvotes: 12
Reputation: 12381
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).
Upvotes: 221
Reputation: 7608
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).
Upvotes: 2