使用ICommand和ServiceLocator以MVVM的方式传递Parent对象以加载Child对象
本文关键字:对象 Parent Child 方式传 加载 ICommand ServiceLocator MVVM 使用 | 更新日期: 2023-09-27 18:25:47
我正在使用MVVMLight工具包创建一个WPF应用程序。我有一个"父"窗体(ParentView),希望通过传递将加载所有"子"对象的"父"对象(parent)来加载"子"窗体(ChildView)。
我已经包含了我认为在任何人的分析中都很重要的3个主要类的代码片段:ViewModelLocator、ChildViewModel、ParentViewModel。我最初想通过实例化ParentView(见下文)在ParentViewModel中实现ICommand属性,但这似乎不正确,因为我试图用MVVM的方式来实现这一点。有人能为以下当前结构提供帮助吗?以及我如何将父母传给孩子?
// ----- ChildViewModel -----
public class ChildViewModel
{
// this ctor doesn't make sense in the MVVM world, right?...
public ChildViewModel(Parent selectedParent)
{
this.Parent = selectedParent;
// ...
}
// how do I plug into this one?...
public ChildViewModel(IParentService parentService)
{
this.ParentService = parentService
// ...
}
// ... removed other code for brevity
}
// ----- ParentViewModel -----
{
public ICommand ShowChildCommand
{
get { return new RelayCommand(() => new ChildView(SelectedParent).Show()); }
}
// ... removed other code for brevity
}
// ----- ViewModelLocator -----
public class ViewModelLocator
{
public ChildModel ChildViewModel
{
get { return ServiceLocator.Current.GetInstance<ChildViewModel>(); }
}
public ParentModel ParentViewModel
{
get { return ServiceLocator.Current.GetInstance<ParentViewModel>(); }
}
public ViewModelLocator()
{
SimpleIoc.Default.Register<IChildService, ChildService>();
SimpleIoc.Default.Register<IParentService, ParentService>();
// ... removed other code for brevity
SimpleIoc.Default.Register<ChildViewModel>();
SimpleIoc.Default.Register<ParentViewModel>();
}
// ... removed other code for brevity
}
//------第2次修订----------------
我采纳了用户@kidshaw的最新建议,但我被不得不在ParentView中创建ChildView实例的评论难住了。我不知道该怎么做。我再次阅读了MSDN上关于信使的文章,但不知道它如何帮助我解决这个问题。我已经包含了以下最新代码。请参考评论部分。
public class ParentViewModel
{
public ICommand ShowChildCommand
{
get { return new RelayCommand(OnLoadChildCommand); }
}
private void OnLoadChildCommand()
{
Messenger.Default.Send(new ParentToChildMessage { Parent = this.CurrentParent });
// ****** this is where I instantiated the child view
// I am sure this is wrong...
var view = new ChildView().Show();
}
public class ParentToChildMessage : MessageBase
{
public Parent Parent { get; set; }
}
...
}
ChildViewModel看起来像:
public class ChildViewModel
{
public ChildViewModel(IChildService service)
{
this.ServiceProxy = service;
this.MessengerInstance.Register<ParentViewModel.ParentToChildMessage>(this, this.OnParentToChildMessage);
this.ChildCollection = new ObservableCollection<Child>();
GetChildInfo(this.CurrentParent);
}
}
在您的示例中,它表明ViewModel正在与视图对话。如果您已经跳转到MVVM模式,则可以避免这种情况。
我希望使用MVVM光中的消息框架来实现这一点。您可以通过这种方式将父视图和子视图分开,并在不将两者耦合在一起的情况下传递数据。您可以在子视图模型中控制子视图的可见性,并在消息处理程序中进行切换。
这篇msdn文章将介绍这些概念。http://msdn.microsoft.com/en-us/magazine/dn745866.aspx.
根据您的编辑
第一个基本步骤是创建一个消息类,将数据从父级传递到子级。
public class ParentToChildMessage : MessageBase
{
/// Include any properties you want to send
}
如果没有要传递的数据,可以使用GenericMessage<>对象来传递bool,为自己节省一些代码。然而,消息是按类型注册的,所以使用泛型意味着您的注册方法将需要进行更多的检查——我稍后会展示他的。
在父视图模型中,您有一个命令ShowChildCommand,我们可以将其用作发送消息的点。
public class ParentViewModel : ViewModelBase
{
public ParentViewModel()
{
}
public ICommand ShowChildCommand
{
get
{
return new RelayCommand(()=>this.MessengerInstance.Send<ParentToChildMessage>(new ParentToChildMessage()));
}
}
}
父视图模型就是这样。接下来,我们在子视图模型中注册一个消息接收器。
public class ChildViewModel : ViewModelBase
{
public ChildViewModel()
{
this.MessengerInstance.Register<ParentToChildMessage>(this, this.OnParentToChildMessage);
}
private void OnParentToChildMessage(ParentToChildMessage obj)
{
// Inspect obj to decide what to do - let's just set as visible
this.IsVisible = true;
}
public bool IsVisible
{
get
{
return _IsVisible;
}
set
{
if (value != _IsVisible)
{
_IsVisible = value;
RaisePropertyChanged();
}
}
}
private bool _IsVisible;
}
您可以在这里看到,在构造函数中,我们向强类型注册了一条消息。如果我们使用泛型,则OnParentToChildMessage的主体必须区分此消息和其他可能的相同类型的消息——这不是很好的代码,尤其是随着时间的推移,您可能会构建多个消息交互。
子视图模型会更新一个简单的bool IsVisible属性-要使其工作,父视图中需要有一个子视图的实例。这将确保创建您的子视图和子视图模型的实例。
我希望这能有所帮助。