C# 从子ViewModel到父ViewModel的属性返回值
在我的WPF MVVM应用程序中,使用Caliburn.Micro,我有一个ViewModel,C# 从子ViewModel到父ViewModel的属性返回值,c#,.net,wpf,mvvm,caliburn.micro,C#,.net,Wpf,Mvvm,Caliburn.micro,在我的WPF MVVM应用程序中,使用Caliburn.Micro,我有一个ViewModel,CreateServiceViewModel,点击一个按钮,就会在一个单独的窗口中打开一个GridView,供用户从中选择一行 我为此创建了另一个ViewModel,MemberSearchViewModel,它有两个属性: private Member selectedMember; public Member SelectedMember { get {
CreateServiceViewModel
,点击一个按钮,就会在一个单独的窗口中打开一个GridView,供用户从中选择一行
我为此创建了另一个ViewModel,MemberSearchViewModel
,它有两个属性:
private Member selectedMember;
public Member SelectedMember
{
get { return selectedMember; }
set { selectedMember = value; }
}
private IList<Member> members;
public IList<Member> Members
{
get { return members; }
set { members = value; }
}
private Member selectedMember;
公共成员选定成员
{
获取{return selectedMember;}
设置{selectedMember=value;}
}
IList私人成员;
公营机构成员
{
获取{返回成员;}
集合{members=value;}
}
如何将SelectedMember值返回调用ViewModel?该视图模型的属性为
服务。SelectedMember
一个选项是将MemberSearchViewModel
存储为CreateServiceViewModel
的字段,并定义CreateServiceViewModel。SelectedMember
属性如下:
public Member SelectedMember
{
get
{
return _memberSearchViewModel.SelectedMember;
}
set
{
_memberSearchViewModel.SelectedMember = value;
}
}
一个选项是将
MemberSearchViewModel
存储为CreateServiceViewModel
的字段,并定义CreateServiceViewModel。SelectedMember
属性如下:
public Member SelectedMember
{
get
{
return _memberSearchViewModel.SelectedMember;
}
set
{
_memberSearchViewModel.SelectedMember = value;
}
}
一个选项是利用
NotifyPropertyChanged
。由于您使用的是ViewModels,因此它们很可能实现了INotifyPropertyChanged
,您可以像框架一样使用它
当CreateServiceViewModel创建MemberSearchViewModel时,它将只订阅PropertyChanged事件:
//This goes wherever you create your child view model
var memberSearchViewModel = new MemberSearchViewModel(); //Or using a service locator, if applicable
memberSearchViewModel.PropertyChanged += OnMemberSearchPropertyChanged;
private void OnMemberSearchPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if(e.PropertyName == "SelectedMember")
{
//Code to respond to a change in the Member
}
}
然后在MemberSearchViewModel中,当用户从网格中选择成员时,只需引发NotifyPropertyChanged事件
编辑:
正如@DNH在注释中正确指出的,如果没有正确清理,使用这样的事件处理程序可能会导致内存泄漏。因此,当您完成MemberSearchViewModel时,请确保取消订阅PropertyChanged
事件。例如,如果您只在用户选择成员之前需要它,您可以将其放入属性更改处理程序本身(我已将其切换为使用类级别变量来保存ViewModel):
一个选项是利用
NotifyPropertyChanged
。由于您使用的是ViewModels,因此它们很可能实现了INotifyPropertyChanged
,您可以像框架一样使用它
当CreateServiceViewModel创建MemberSearchViewModel时,它将只订阅PropertyChanged事件:
//This goes wherever you create your child view model
var memberSearchViewModel = new MemberSearchViewModel(); //Or using a service locator, if applicable
memberSearchViewModel.PropertyChanged += OnMemberSearchPropertyChanged;
private void OnMemberSearchPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if(e.PropertyName == "SelectedMember")
{
//Code to respond to a change in the Member
}
}
然后在MemberSearchViewModel中,当用户从网格中选择成员时,只需引发NotifyPropertyChanged事件
编辑:
正如@DNH在注释中正确指出的,如果没有正确清理,使用这样的事件处理程序可能会导致内存泄漏。因此,当您完成MemberSearchViewModel时,请确保取消订阅PropertyChanged
事件。例如,如果您只在用户选择成员之前需要它,您可以将其放入属性更改处理程序本身(我已将其切换为使用类级别变量来保存ViewModel):
怎么样
public interface INotifyMe<T>
{
T ResultToNotify { get; set; }
}
public class CreateServiceViewModel : ViewModelBase, INotifyMe<Member>
{
// implement the interface as you like...
}
public class MemberSearchViewModel : ViewModelBase
{
public MemberSearchViewModel(INotifyMe<Member> toBeNotified)
{
// initialize field and so on...
}
}
怎么样
public interface INotifyMe<T>
{
T ResultToNotify { get; set; }
}
public class CreateServiceViewModel : ViewModelBase, INotifyMe<Member>
{
// implement the interface as you like...
}
public class MemberSearchViewModel : ViewModelBase
{
public MemberSearchViewModel(INotifyMe<Member> toBeNotified)
{
// initialize field and so on...
}
}
作为我评论的后续,下面是一个使用
Prism
的示例-我从未使用过Caliburn
创建事件-事件的有效负载将是您选择的成员:
public class YourEvent:CompositePresentationEvent<YourEventPayload>{}
public类YourEvent:CompositePresentationEvent{}
发布事件:
EventAggregator.GetEvent<YourEvent>().Publish(YourEventPayload);
EventAggregator.GetEvent<YourEvent>().Subscribe((i) => ...);
EventAggregator.GetEvent().Publish(YourEventPayload);
订阅活动:
EventAggregator.GetEvent<YourEvent>().Publish(YourEventPayload);
EventAggregator.GetEvent<YourEvent>().Subscribe((i) => ...);
EventAggregator.GetEvent().Subscribe((i)=>…);
作为我评论的后续,下面是一个使用Prism
的示例-我从未使用过Caliburn
创建事件-事件的有效负载将是您选择的成员:
public class YourEvent:CompositePresentationEvent<YourEventPayload>{}
public类YourEvent:CompositePresentationEvent{}
发布事件:
EventAggregator.GetEvent<YourEvent>().Publish(YourEventPayload);
EventAggregator.GetEvent<YourEvent>().Subscribe((i) => ...);
EventAggregator.GetEvent().Publish(YourEventPayload);
订阅活动:
EventAggregator.GetEvent<YourEvent>().Publish(YourEventPayload);
EventAggregator.GetEvent<YourEvent>().Subscribe((i) => ...);
EventAggregator.GetEvent().Subscribe((i)=>…);
事件聚合器是您可以使用的。。。我确信这是众多解决方案中的一个
public class MessageNotifier{
public object Content{get;set;}
public string Message {get;set;}
}
//MEF bits here
public class HelloWorldViewModel: Screen, IHandle<MessageNotifier>{
private readonly IEventAggregator _eventAggregator
//MEF constructor bits
public YourViewModel(IEventAggregator eventAggregator){
_eventAggregator = eventAggregator;
}
public override OnActivate(){
_eventAggregator.Subscribe(this);
}
public override OnDeactivate(){
_eventAggregator.UnSubscribe(this);
}
//I Handle all messages with this signature and if the message applies to me do something
//
public void Handle(MesssageNotifier _notifier){
if(_notifier.Message == "NewSelectedItem"){
//do something with the content of the selectedItem
var x = _notifier.Content
}
}
}
//MEF attrs
public class HelloWorld2ViewModel: Screen{
private readonly IEventAggregator _eventAggregator
//MEF attrs
public HelloWorld2ViewModel(IEventAggregator eventAggregator){
_eventAggregator = eventAggregator;
}
public someobject SelectedItem{
get{ return _someobject ;}
set{ _someobject = value;
NotifyOfPropertyChange(()=>SelectedItem);
_eventAggregator.Publish(new MessageNotifier(){ Content = SelectedItem, Message="NewSelectedItem"});
}
}
公共类消息通知程序{
公共对象内容{get;set;}
公共字符串消息{get;set;}
}
//这里是MEF位
公共类HelloWorldViewModel:Screen,IHandle{
私有只读IEventAggregator\u事件聚合器
//MEF构造函数位
公共YourViewModel(IEventAggregator事件聚合器){
_eventAggregator=eventAggregator;
}
公共覆盖OnActivate(){
_eventAggregator.Subscribe(此);
}
公共覆盖OnDeactivate(){
_事件聚合器。取消订阅(此);
}
//我处理所有带有此签名的邮件,如果邮件适用于我,请执行某些操作
//
公共无效句柄(MessageNotifier\u notifier){
如果(_notifier.Message==“NewSelectedItem”){
//对selectedItem的内容执行一些操作
var x=\u notifier.Content
}
}
}
//MEF吸引子
公共类HelloWorld2ViewModel:屏幕{
私有只读IEventAggregator\u事件聚合器
//MEF属性
公共HelloWorld2ViewModel(IEventAggregator事件聚合器){
_eventAggregator=eventAggregator;
}
公共someobject SelectedItem{
获取{return\u someobject;}
设置{u someobject=value;
NotifyOfPropertyChange(()=>SelectedItem);
_Publish(newmessagenotifier(){Content=SelectedItem,Message=“NewSelectedItem”});
}
}
EventAggregator是您可以使用的解决方案……我确信它是众多解决方案之一
public class MessageNotifier{
public object Content{get;set;}
public string Message {get;set;}
}
//MEF bits here
public class HelloWorldViewModel: Screen, IHandle<MessageNotifier>{
private readonly IEventAggregator _eventAggregator
//MEF constructor bits
public YourViewModel(IEventAggregator eventAggregator){
_eventAggregator = eventAggregator;
}
public override OnActivate(){
_eventAggregator.Subscribe(this);
}
public override OnDeactivate(){
_eventAggregator.UnSubscribe(this);
}
//I Handle all messages with this signature and if the message applies to me do something
//
public void Handle(MesssageNotifier _notifier){
if(_notifier.Message == "NewSelectedItem"){
//do something with the content of the selectedItem
var x = _notifier.Content
}
}
}
//MEF attrs
public class HelloWorld2ViewModel: Screen{
private readonly IEventAggregator _eventAggregator
//MEF attrs
public HelloWorld2ViewModel(IEventAggregator eventAggregator){
_eventAggregator = eventAggregator;
}
public someobject SelectedItem{
get{ return _someobject ;}
set{ _someobject = value;
NotifyOfPropertyChange(()=>SelectedItem);
_eventAggregator.Publish(new MessageNotifier(){ Content = SelectedItem, Message="NewSelectedItem"});
}
}
公共类消息通知程序{
公共对象内容{get;set;}
公共字符串消息{get;set;}
}
//这里是MEF位
公共类HelloWorldViewModel:Screen,IHandle{
私有只读IEventAggregator\u事件聚合器
//MEF构造函数位
公共视图模式