我希望能够通过UserControl
将复杂模型(许多属性)绑定到DependencyProperty
,如果在UserControl
中编辑模型,我希望看到此编辑的信息在我的绑定模型中。
示例应用程序:Model,UserControl(xaml + cs),MainWindow(xaml + cs)。我没有ViewModel来简化想法。
型号:
public class MyModel : INotifyPropertyChanged
{
private string _surname;
private string _name;
public string Name
{
get => _name;
set
{
_name = value;
OnPropertyChanged();
}
}
public string Surname
{
get => _surname;
set
{
_surname = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
MyModelEditor.xaml(在Grid中):
<DockPanel>
<TextBox Text="{Binding MyModel.Name}"/>
<TextBox Text="{Binding MyModel.Surname}"/>
</DockPanel>
在UserControl根元素中还包含此行:
DataContext="{Binding RelativeSource={RelativeSource Self}}"
MyModelEditor.xaml.cs:
public partial class MyModelEditor : UserControl
{
public MyModel MyModel
{
get => (MyModel)GetValue(MyModelProperty);
set => SetValue(MyModelProperty, value);
}
public static readonly DependencyProperty MyModelProperty =
DependencyProperty.Register("MyModel", typeof(MyModel), typeof(MyModelEditor), new FrameworkPropertyMetadata(null));
public MyModelEditor()
{
InitializeComponent();
}
}
MainWindow.xaml(在Grid中):
<DockPanel>
<Button DockPanel.Dock="Bottom" Content="Press Me!" Click="ButtonBase_OnClick"/>
<controls:MyModelEditor MyModel="{Binding MyModel}"/>
</DockPanel>
MainWindow.xaml.cs:
public partial class MainWindow : Window, INotifyPropertyChanged
{
private MyModel _myModel;
public MyModel MyModel
{
get => _myModel;
set
{
_myModel = value;
OnPropertyChanged();
}
}
public MainWindow()
{
InitializeComponent();
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
MessageBox.Show(MyModel?.Name);
}
}
我的测试场景:在文本框中键入文本,按下按钮。
当前行为:按下按钮后的消息为空
预期行为:按下按钮后的消息与文本框中的消息相同。
我不想分别绑定到所有属性,因为将来我会有两个以上的属性。
为什么目前的做法不起作用? 我怎样才能实现目标?
答案 0 :(得分:3)
您显然没有在UserControl的XAML中将UserControl实例用作绑定源。一种方法是设置Binding的RelativeSource:
<TextBox Text="{Binding MyModel.Name,
RelativeSource={RelativeSource AncestorType=UserControl}}"/>
但是,为此,您根本不需要新的依赖项属性。只需将UserControl的DataContext绑定到MyModel实例,例如
<controls:MyModelEditor DataContext="{Binding MyModel}"/>
UserControl的XAML中的Bindings会自动使用MyModel对象,如下所示:
<DockPanel>
<TextBox Text="{Binding Name}"/>
<TextBox Text="{Binding Surname}"/>
</DockPanel>
答案 1 :(得分:1)
对于您的两个TextBox
控件,您应该在绑定模式下使用Binding
模式(ms docs)定义他们的TwoWay
。基本上,这将确保数据流在两个方向上工作(即从视图模型到视图,反之亦然):
<DockPanel>
<TextBox Text="{Binding MyModel.Name, Mode=TwoWay}"/>
<TextBox Text="{Binding MyModel.Surname, Mode=TwoWay}"/>
</DockPanel>
作为一种良好做法,您应该始终明确定义Binding
的模式(注意:默认情况下,它是 OneWay
TwoWay
- how to know which is the default?)。
另一个提示是继续使用MvvmHelpers nuget(github project),这可以免除您实施INotifyPropertyChanged
的时间。此外,你不应该重新发明轮子
编辑 :修复程序位于您的GitHub存储库中
这里要注意两件事
MyModel
),因此始终为null
DependencyPropery
时,您无需创建UserControl
。您可以简单地绑定DataContext
本身