用户控件数据上下文绑定
UserControl DataContext Binding
我的解决方案中有三个项目:
- 我的主要 WPF 应用程序包含一个 MainWindow + MainViewModel
- 带有 UserControl 的 UserControl 库(ConfigEditorView)
- UIProcess class 与 UserControl 的 ViewModel (ConfigEditorViewModel)
在我的 MainWindow 中,我想将 UserControl 与 UIProcess 的 ViewModel 一起使用。
首先我在 MainWindow 中设置了 UserControl:
<TabItem Header="Editor">
<Grid>
<cel:ConfigEditorView DataContext="{Binding ConfEditModel, NotifyOnSourceUpdated=True, NotifyOnTargetUpdated=True, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</Grid>
</TabItem>
我不知道我需要这些属性中的哪一个,所以我把它们放在一起但它仍然不起作用。
然后我在 MainViewModel 中设置了这个:
public ConfigEditorViewModel ConfEditModel { get; set; }
使用绑定到 Button 的简单方法:
private void doSomething()
{
ConfEditModel = new ConfigEditorViewModel("Hello World");
}
我的 ConfigEditorViewModel 基本上是这样的:
public class ConfigEditorViewModel : ViewModelBase
{
private string _Description;
public string Description
{
get
{
return _Description;
}
set
{
_Description = value;
base.RaisePropertyChanged();
}
}
public ConfigEditorViewModel(string t)
{
Description = t;
}
}
说明绑定到我的用户控件中的文本框。
<TextBox Grid.Row="1" Grid.Column="1" Margin="0,0,0,10" Text="{Binding Description}"/>
当我启动应用程序并单击按钮时,文本框应该包含 "Hello World" 但它是空的。
我做错了什么?
您的视图模型(以及可选的模型)需要实现 INotifyPropertyChanged。
绑定并不神奇。没有内置机制允许在普通旧 属性 的值更改时通知代码。您必须对其进行轮询以检查是否发生了更改,这在性能方面非常糟糕。
所以绑定将查看它们所绑定的对象,看看它们是否实现了 INotifyPropertyChanged,如果是,将订阅 PropertyChanged 事件。这样,当您更改 属性 并触发事件时,绑定会收到通知并更新 UI.
请注意,您必须实现接口并正确使用它。 This example says it's for 2010,但它工作正常。
我给了你一个笼统的答案:
在 "real(a usercontrol you wanna use with different viewmodels with different property names)" 用户控件中,您 仅绑定到您自己的 DependencyProperties,然后使用 ElementName 或 RelativeSource 绑定 和您应该永远不要在 UserControl 中设置 DataContext。
<UserControl x:Name="myRealUC" x:class="MyUserControl">
<TextBox Text="{Binding ElementName=myRealUC, Path=MyOwnDPIDeclaredInMyUc, Path=TwoWay}"/>
<UserControl>
如果这样做,您可以在任何视图中轻松使用此用户控件,例如:
<myControls:MyUserControl MyOwnDPIDeclaredInMyUc="{Binding MyPropertyInMyViewmodel}"/>
为了完整性:依赖关系 属性
public readonly static DependencyProperty MyOwnDPIDeclaredInMyUcProperty = DependencyProperty.Register(
"MyOwnDPIDeclaredInMyUc", typeof(string), typeof(MyUserControl), new PropertyMetadata(""));
public bool MyOwnDPIDeclaredInMyUc
{
get { return (string)GetValue(MyOwnDPIDeclaredInMyUcProperty); }
set { SetValue(MyOwnDPIDeclaredInMyUcProperty, value); }
}
我的解决方案中有三个项目:
- 我的主要 WPF 应用程序包含一个 MainWindow + MainViewModel
- 带有 UserControl 的 UserControl 库(ConfigEditorView)
- UIProcess class 与 UserControl 的 ViewModel (ConfigEditorViewModel)
在我的 MainWindow 中,我想将 UserControl 与 UIProcess 的 ViewModel 一起使用。
首先我在 MainWindow 中设置了 UserControl:
<TabItem Header="Editor">
<Grid>
<cel:ConfigEditorView DataContext="{Binding ConfEditModel, NotifyOnSourceUpdated=True, NotifyOnTargetUpdated=True, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</Grid>
</TabItem>
我不知道我需要这些属性中的哪一个,所以我把它们放在一起但它仍然不起作用。
然后我在 MainViewModel 中设置了这个:
public ConfigEditorViewModel ConfEditModel { get; set; }
使用绑定到 Button 的简单方法:
private void doSomething()
{
ConfEditModel = new ConfigEditorViewModel("Hello World");
}
我的 ConfigEditorViewModel 基本上是这样的:
public class ConfigEditorViewModel : ViewModelBase
{
private string _Description;
public string Description
{
get
{
return _Description;
}
set
{
_Description = value;
base.RaisePropertyChanged();
}
}
public ConfigEditorViewModel(string t)
{
Description = t;
}
}
说明绑定到我的用户控件中的文本框。
<TextBox Grid.Row="1" Grid.Column="1" Margin="0,0,0,10" Text="{Binding Description}"/>
当我启动应用程序并单击按钮时,文本框应该包含 "Hello World" 但它是空的。
我做错了什么?
您的视图模型(以及可选的模型)需要实现 INotifyPropertyChanged。
绑定并不神奇。没有内置机制允许在普通旧 属性 的值更改时通知代码。您必须对其进行轮询以检查是否发生了更改,这在性能方面非常糟糕。
所以绑定将查看它们所绑定的对象,看看它们是否实现了 INotifyPropertyChanged,如果是,将订阅 PropertyChanged 事件。这样,当您更改 属性 并触发事件时,绑定会收到通知并更新 UI.
请注意,您必须实现接口并正确使用它。 This example says it's for 2010,但它工作正常。
我给了你一个笼统的答案:
在 "real(a usercontrol you wanna use with different viewmodels with different property names)" 用户控件中,您 仅绑定到您自己的 DependencyProperties,然后使用 ElementName 或 RelativeSource 绑定 和您应该永远不要在 UserControl 中设置 DataContext。
<UserControl x:Name="myRealUC" x:class="MyUserControl">
<TextBox Text="{Binding ElementName=myRealUC, Path=MyOwnDPIDeclaredInMyUc, Path=TwoWay}"/>
<UserControl>
如果这样做,您可以在任何视图中轻松使用此用户控件,例如:
<myControls:MyUserControl MyOwnDPIDeclaredInMyUc="{Binding MyPropertyInMyViewmodel}"/>
为了完整性:依赖关系 属性
public readonly static DependencyProperty MyOwnDPIDeclaredInMyUcProperty = DependencyProperty.Register(
"MyOwnDPIDeclaredInMyUc", typeof(string), typeof(MyUserControl), new PropertyMetadata(""));
public bool MyOwnDPIDeclaredInMyUc
{
get { return (string)GetValue(MyOwnDPIDeclaredInMyUcProperty); }
set { SetValue(MyOwnDPIDeclaredInMyUcProperty, value); }
}