我有一个名为MainContentView.xaml
的主视图,我将DataContext设置为名为MainContentViewModel.cs
的ViewModel。在这里,我可以更新UI中出现的值,就像普通的MVVM一样
它看起来像这样:
<UserControl x:Class="namespace:MyProject.View.Home.MainContentView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:UserTools="clr-namespace:MyProject.View.Tools"
xmlns:ViewModel="clr-namespace:MyProject.ViewModel.Home"
mc:Ignorable="d" >
<UserControl.DataContext>
<ViewModel:MainContentViewModel />
</UserControl.DataContext>
<Grid x:Name="mainGrid">
<!-- Normal objects -->
<StackPanel>
<Label Text="Im a label" />
<TextBox />
</StackPanel>
<!-- My Custom Object -->
<UserTools:MyCustomUserControl x:Name="myUserControl" />
</Grid>
</UserControl>
我的MainContentViewModel.cs
看起来像这样:
public class MainContentViewModel : INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged;
private string myLabel = "";
public string MyLabel {
get { return this.myLabel; }
set {
this.myLabel = value;
OnPropertyChangedEvent("MyLabel");
}
}
public MainContentViewModel() {
MyLabel = string.Format("my label text");
}
protected virtual void OnPropertyChangedEvent(string _propertyName) {
var _handler = this.PropertyChanged;
if(_handler != null) { _handler(this, new PropertyChangedEventArgs(_propertyName)); }
}
}
现在我想通过它自己的MyCustomUserControl.xaml
在MyCustomUserControlViewModel.cs
中设置一些属性
我的MyCustomUserControl.xaml
看起来像这样:
<UserControl x:Class="MyProject.View.Tools.MyCustomUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ViewModel="clr-namespace:MyProject.ViewModel.Tools"
mc:Ignorable="d" >
<UserControl.DataContext>
<ViewModel:MyCustomUserControlViewModel />
</UserControl.DataContext>
<Grid x:Name="mainGrid">
<Label Content="{Binding myCustomLabel}" />
</Grid>
</UserControl>
我的MyCustomUserControlViewModel.cs
看起来像这样:
public class MyCustomUserControlViewModel : INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged;
private string myCustomLabel = "";
public string MyCustomLabel {
get { return this.myCustomLabel; }
set {
this.myCustomLabel = value;
OnPropertyChangedEvent("MyCustomLabel");
}
}
public MyCustomUserControlViewModel() {
MyCustomLabel = string.Format("my custom label text");
}
protected virtual void OnPropertyChangedEvent(string _propertyName) {
var _handler = this.PropertyChanged;
if(_handler != null) { _handler(this, new PropertyChangedEventArgs(_propertyName)); }
}
}
现在我想从MainContentViewModel.cs
更新MyCustomLabel
上的MyUserCustomUserControl.xaml
属性,我想我必须通过MyCustomUserControlViewModel.cs
进行更新,所以我可以保持MVVM模式。
我尝试过这样的事情:
在MainContentViewModel.cs
private MyCustomUserControlViewModel _viewModel = new MyCustomUserControlViewModel ();
(...)
public MainContentViewModel() {
(...)
_viewModel.SetMyCustomLabel("my new custom label text");
}
并在MyCustomUserControlViewModel.cs
public void SetMyCustomLabel(string _text) {
MyCustomLabel = _text;
}
但这不起作用。我猜这是因为我正在实例化另一个MyCustomUserControlViewModel.cs
对象。
那么,我该怎么办呢?
更新和工作(谢谢Sheridan)
我选择了Sheridan的一个解决方案,最终得到了这个有效的解决方案。在我的MainContentView.xaml
:
(...)
<UserTools:MyCustomUserControl DataContext="{Binding ChildViewModel, Mode=OneWay}" />
在我的MainContentViewModel.cs
:
private MyCustomUserControlViewModel childViewModel = new MyCustomUserControlViewModel();
public MyCustomUserControlViewModel ChildViewModel {
get { return childViewModel; }
private set { childViewModel = value; OnPropertyChangedEvent("ChildViewModel"); }
}
然后我可以这样做:
public MainContentViewModel() {
(...)
ChildViewModel.SetMyCustomLabel("my new custom label text");
}
答案 0 :(得分:2)
如果您的父视图模型可以访问所使用的实际子视图模型实例(由于您实例化子视图模型的方式,它可能不是这样),那么您可以简单地完成此操作:
public MainContentViewModel() {
(...)
_viewModel.CustomLabel = "my new custom label text";
}
<强> 1 强>
一种解决方案是将子视图模型从子视图中移除到父视图模型,然后使用ContentControl
和DataTemplate
显示子视图:
<DataTemplate DataType="{x:Type ViewModels:MyCustomUserControlViewModel}">
<Views:MyCustomUserControlView />
</DataTemplate>
...
在MainContentViewModel中:
public MyCustomUserControlViewModel ChildViewModel
{
get { return childViewModel; }
private set { childViewModel = value; NotifyPropertyChanged("ChildViewModel"); }
}
...
<Grid x:Name="mainGrid">
<!-- Normal objects -->
<StackPanel>
<Label Text="Im a label" />
<TextBox />
</StackPanel>
<!-- My Custom Object -->
<ContentControl x:Name="myUserControl" Content="{Binding ChildViewModel}" />
</Grid>
这样做可以让你简单地调用属性,如我的第一个例子所示。
<强> 2 强>
一种替代方法是将属性移动到父视图模型并直接从子UserControl
绑定到它:
<Grid x:Name="mainGrid">
<Label Content="{Binding DataContext.myCustomLabel, RelativeSource={RelativeSource
AncestorType={x:Type Views:MainContentView}}}" />
</Grid>
更新&gt;&gt;&gt;
第3 强>
好的,我刚才有了另一个想法......你可以将另一个属性添加到父视图模型中,并将数据绑定到子视图模型,如下所示:
<UserTools:MyCustomUserControl DataContext="{Binding ChildViewModel,
Mode=OneWayToSource}" x:Name="myUserControl" />
这只是猜测,但可能能够像这样挂钩到子视图模型......然后你可以在父视图模型中执行此操作:
if (ChildViewModel != null) ChildViewModel.CustomLabel = "my new custom label text";
<强> 4 强>
实际上......我刚才有了另一个想法。您可以从父视图模型中的属性绑定到UserControl
,如果您向其添加DependencyProperty
:
<UserTools:MyCustomUserControl CustomLabel="{Binding CustomLabelInParentViewModel}"
x:Name="myUserControl" />
在这种情况下,您可以简单地从子视图模型中删除该属性。