I just can’t find the missing piece. My UserControl doesn’t update the binded property. I’m creating a new UserControl in my code behind. The SetValue and GetValue method are getting called. If the viewModel is initializing some value, my UserControl gets it. But if I change the text in the Textbox, the viewmodel doesn’t hold this value.
My Code:
public partial class MyUserControl : UserControl, INotifyPropertyChanged
{
public MyUserControl()
{
InitializeComponent();
}
public static readonly DependencyProperty CommentToAddProperty=
DependencyProperty.Register(
nameof(CommentToAdd),
typeof(string),
typeof(MyUserControl),
new FrameworkPropertyMetadata(
default(string),
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
OnCommentChange));
public string CommentToAdd
{
get => (string)GetValue(CommentToAddProperty);
set => SetValue(CommentToAddProperty, value);
}
private static void OnCommentChange(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var myUC = d as MyUserControl;
var comment = e.NewValue as string;
myUC.CommentToAdd = comment;
myUC.RaisePropertyChanged(nameof(CommentToAdd));
}
public partial class SomeWindow: Window
{
public SomeWindow()
{
InitializeComponent();
_vm = new MyViewModel();
DataContext = _vm;
var userControl = new UserControls.MyUserControl
{
CommentToAdd = _vm.CommentToAdd,
}
\\Add usercontrol to a grid
}
}
public partial class MyViewModel : ObservableObject
{
[ObservableProperty]
private string _commentToAdd;
}
This is my XAML code in my UserControl
<TextBox
Grid.Column="0"
Text="{Binding Path= CommentToAdd, Mode=TwoWay,
RelativeSource={RelativeSource
Mode=FindAncestor,
AncestorType=local:MyUserControl},
UpdateSourceTrigger=PropertyChanged}"/>
>Solution :
The assignment
CommentToAdd = _vm.CommentToAdd
does not establish a data binding of the CommentToAdd property.
In order to create a Binding, you would have to write
userControl.SetBinding(
MyUserControl.CommentToAddProperty,
new Binding("CommentToAdd"));
or without relying on the assigned DataContext and on the fact that the property binds TwoWay by default
userControl.SetBinding(
MyUserControl.CommentToAddProperty,
new Binding
{
Source = _vm,
Path = new PropertyPath("CommentToAdd"),
Mode = BindingMode.TwoWay
});
However, you should usually not be creating UI elements in code behind. Better declare the control in XAML:
<MyUserControl CommentToAdd="{Binding CommentToAdd}"/>