我有一个AddClientViewModel,由2个视图(AddClientView和SuggestedAddressesView)引用。 AddClientView是一个具有地址字段的表单。表单有一个验证按钮,使用地理编码验证输入的地址。如果返回多个地址,则打开SuggestedAddressesView。
以下是我目前的工作方式:
AddClientViewModel:
private void ValidateExecute(object obj)
{
SuggestedAddresses = new ObservableCollection<DBHelper.GeocodeService.GeocodeResult>(GeoCodeTest.SuggestedAddress(FormattedAddress));
....
if (SuggestedAddresses.Count > 0)
{
var window = new SuggestedAddressesView(this);
window.DataContext = this;
window.Show();
}
}
这是SuggestedAddressesView构造函数,其中AddClientViewModel从ViewModelBase继承
public SuggestedAddressesView(ViewModelBase viewModel)
{
InitializeComponent();
viewModel.ClosingRequest += (sender, e) => this.Close();
}
我遇到的另一个问题是当我从AddClientViewModel调用OnClosingRequest()时... AddClientView和SuggestedAddressesView都关闭了。我知道这是因为两个视图都引用了相同的ViewModel。这不是我想要的行为。我希望能够独立关闭任何一个窗口。
从ViewModel正确的MVVM结构打开一个视图,我将如何独立关闭窗口?
答案 0 :(得分:5)
只要从VM引用UI元素(在本例中为View),就会违反建议的MVVM准则。只有这样我们才能知道在VM中创建Window
对象是错误的。
现在纠正这个:
AddClientView
和SuggestedAddressesView
拥有自己的VM。太好了!从VM实施视图打开/关闭:
Messenger
(MVVM Light),EventAggregator
(PRISM)等方法当您需要打开/关闭视图并在视图中执行实际操作时,从VM向视图发送“消息”。 使用“Messenger”方法处理查看打开:
AddClientViewModel
必须要求SuggestedAddressesView
开启。SuggestedAddresses.Count > 0
时,您会向AddClientView
发送消息,要求其打开SuggestedAddressesView
。AddClientView.xaml.cs
收到此消息后,您将执行您当前在VM中执行的操作。创建SuggestedAddressesView
的对象并在其上调用.Show()
。DataContext
SuggestedAddressesView
分配为SuggestedAddressesViewModel
。就是这样。现在,当AddClientViewModel
想要显示SuggestedAddressesView
时,它会向其自己的视图发送消息,而视图又会创建并显示SuggestedAddressesView
。这样VM就不会引用任何View,我们会继续遵守MVVM标准。
使用“Messenger”方法处理查看关闭:
View
非常简单。再次当您需要从VM关闭View时,您会向其自己的View发送一条消息,要求将其关闭。.Hide()
/ .Close()
关闭,或者您想要删除它。在这个中,每个VM处理它自己的View关闭,你没有任何相互连接的依赖。
您可以使用this作为起点来指导您处理此方法的“消息”。它有一个附加的下载,你可以看到Messenger
如何工作。这是MVVM Light,如果您不使用它或使用其他/您自己的MVVM实现,请将其用作指南以帮助您获得所需的内容。
答案 1 :(得分:0)
您可以使用RelayCommand,以便按如下方式发送参数:
Command="{Binding CloseWindowCommand, Mode=OneWay}"
CommandParameter="{Binding ElementName=TestWindow}"
通过使用此功能,您可以关闭各个视图。
示例:
public ICommand CloseCommand
{
get
{
return new RelayCommand(OnClose, IsEnable);
}
}
public void OnClose(object param)
{
AddClientView/SuggestedAddressesView Obj = param as AddClientView/SuggestedAddressesView;
obj.Close();
}
答案 2 :(得分:-1)
从ViewModel打开窗口:
为打开窗口创建NavigationService.cs类: 让NavigationService.cs
现在将以下代码放在该类文件中。
public void ShowWindow1Screen(Window1ViewModel window1ViewModel)
{
Window1= new Window1();
Window1.DataContext = window1ViewModel;
Window1.Owner = Window1View;
Window1.ShowDialog();
}
然后。 创建NavigationService.cs类MainWindowViewModel文件的实例。 然后
Window1ViewModel window1ViewModel = new Vindow1ViewModel();
window1ViewModel.Name = MainWindowTextValue;
NavigationService navigationService = new NavigationService();
navigationService.ShowWindow1Screen(window1ViewModel);