C# MVVM灯光投射消息
我有以下行为:C# MVVM灯光投射消息,c#,silverlight,mvvm,mvvm-light,C#,Silverlight,Mvvm,Mvvm Light,我有以下行为: public class NavigateAndBroadcastAction : NavigateToPageAction { protected override void Invoke(object parameter) { base.Invoke(parameter); Messenger.Default.Send
public class NavigateAndBroadcastAction : NavigateToPageAction
{
protected override void Invoke(object parameter)
{
base.Invoke(parameter);
Messenger.Default.Send<NavigatingMessage<ViewModelBase>>(new NavigatingMessage<ViewModelBase>(this, PassedObject), NavigationToken);
}
public ViewModelBase PassedObject
{
get { return (ViewModelBase)GetValue(PassedObjectProperty); }
set { SetValue(PassedObjectProperty, value); }
}
// Using a DependencyProperty as the backing store for PassedObject. This enables animation, styling, binding, etc...
public static readonly DependencyProperty PassedObjectProperty = DependencyProperty.Register("PassedObject", typeof(ViewModelBase), typeof(NavigateAndBroadcastAction), new PropertyMetadata(null));
...
}
公共类NavigateAndBroadcastAction:NavigateToPageAction
{
受保护的覆盖无效调用(对象参数)
{
base.Invoke(参数);
sender.Default.Send(新导航消息(this,PassedObject),NavigationToken);
}
公共视图模型库传递对象
{
获取{return(ViewModelBase)GetValue(PassedObjectProperty);}
set{SetValue(PassedObjectProperty,value);}
}
//使用DependencyProperty作为PasseObject的后备存储。这将启用动画、样式设置、绑定等。。。
public static readonly dependencProperty PassedObjectProperty=dependencProperty.Register(“PassedObject”、typeof(ViewModelBase)、typeof(NavigateAndBroadcastAction)、new PropertyMetadata(null));
...
}
它基本上使用NavigateToPageAction(也可在Blend中使用),但也允许我广播ViewModel对象(我使用它从列表页面导航到详细页面并传递所选对象)
Xaml如下所示:(PassedObject绑定到从ViewModelBase继承的DetailViewModel实例)
现在,我想注册信息:
Messenger.Default.Register<NavigatingMessage<DetailViewModel>>(this, NavigationToken, true, Action);
Messenger.Default.Register(this,NavigationToken,true,Action);
但这不起作用。有效的方法是注册导航消息
,然后将收到的消息强制转换为导航消息
。有办法吗
是否可以这样做,使messenger检测到正在发送的对象的实际类型,并正确地将其传递给注册为该类型的对象?如果您以messenger.Default.send(新导航消息(此,PasseObject)的形式发送消息您可以根据需要接收消息,而无需强制转换。一种可能的方法是使用反射发送消息,方法是在运行时使用正确的泛型类型创建消息。
另一种方法是使用
动态和类型推断:
protected override void Invoke(object parameter)
{
base.Invoke(parameter);
dynamic viewModel = PassedObject;
Messenger.Default.Send(GetMessage(this, viewModel), NavigationToken);
}
private NavigatingMessage<T> GetMessage<T>(NavigateToPageAction action, T item)
{
return new NavigatingMessage<T>(action, item);
}
protected override void Invoke(对象参数)
{
base.Invoke(参数);
动态视图模型=传递对象;
Send(GetMessage(this,viewModel),NavigationToken);
}
private NavigatingMessage GetMessage(NavigateToPageAction操作,T项)
{
返回新的导航消息(操作、项目);
}
使用反射的版本有点混乱:
protected override void Invoke(object parameter)
{
base.Invoke(parameter);
Send(PassedObject, NavigationToken);
}
void Send(ViewModelBase objectToSend, string navigationToken)
{
var genericMessageType = typeof(NavigatingMessage<>)
var viewModelType = objectToSend.GetType();
var messageType = genericMessageType.MakeGenericType(viewModelType);
var message = Activator.CreateInstance(messageType, this, objectToSend);
var method = typeof(Messenger).GetMethods()
.Single(x => x.Name == "Send" &&
x.GetParameters().Count() == 2 &&
x.GetParameters()
.First()
.ParameterType
.GetGenericTypeDefinition()
== genericMessageType);
method.MakeGenericMethod(viewModelType)
.Invoke(Messenger.Default, new [] { message, navigationToken });
}
protected override void Invoke(对象参数)
{
base.Invoke(参数);
发送(PassedObject、NavigationToken);
}
void发送(ViewModelBase对象发送,字符串导航令牌)
{
var genericMessageType=typeof(导航消息)
var viewModelType=objectToSend.GetType();
var messageType=genericMessageType.MakeGenericType(viewModelType);
var message=Activator.CreateInstance(messageType、this、objectToSend);
var method=typeof(Messenger).GetMethods()
.Single(x=>x.Name==“发送”&&
x、 GetParameters().Count()==2&&
x、 GetParameters()
.First()
.参数类型
.GetGenericTypeDefinition()
==genericMessageType);
方法。MakeGenericMethod(viewModelType)
.Invoke(Messenger.Default,new[]{message,navigationToken});
}
此代码假定NavigationToken
是字符串
。如果不是,只需更改Send
方法的第二个参数的类型。如果Messenger
只包含Send
方法的一个重载,则可以简化Single
中的条件。另一方面,如果存在大量重载该方法,您可能需要对其进行优化。这是当前版本的MVVM Light的一个限制。我正在考虑在将来改进它,但这很棘手…为什么它不起作用?您是否收到编译错误?异常?不,消息simple没有得到传递您可以发送cor的消息吗rect类型?我该怎么做?我希望行为是通用的,这样在Xaml中我可以绑定到从ViewModelBase继承的任何对象..是的,但这会破坏行为的目的-我希望能够发送从ViewModelBaseMM继承的任何对象,那么我担心您将不得不接受强制转换:(@LOSTCODER:那不对。请看我的答案,你可能会学到一些新东西:-)@DanielHilgarth:是的,我看到了,投了赞成票!:)真的很干净,兄弟。我知道反射可以解决这个问题,但使用动态太过圆滑了!非常感谢…请看我的答案。这对实现这个功能有帮助吗?DLR非常强大。你能举个反射方法的例子吗?我的目标是WP7,事实证明,它不支持动态关键字a-may-zing:)我不得不稍微修改一下(删除了Count()==2之后的第二个条件,因为它引发了异常,而不是“method.MakeGenericMethod(viewModelType)”,我使用了“method.MakeGenericMethod(messageType)”,它就像一个符咒:)我不知道反射有这样的可能性:)@TomášBezouška:我只使用与代码中的实际方法命名相同的存根方法对其进行了测试。很可能我对这些方法使用了一些错误的类型,所以您的更改应该是正确的。:-)
protected override void Invoke(object parameter)
{
base.Invoke(parameter);
Send(PassedObject, NavigationToken);
}
void Send(ViewModelBase objectToSend, string navigationToken)
{
var genericMessageType = typeof(NavigatingMessage<>)
var viewModelType = objectToSend.GetType();
var messageType = genericMessageType.MakeGenericType(viewModelType);
var message = Activator.CreateInstance(messageType, this, objectToSend);
var method = typeof(Messenger).GetMethods()
.Single(x => x.Name == "Send" &&
x.GetParameters().Count() == 2 &&
x.GetParameters()
.First()
.ParameterType
.GetGenericTypeDefinition()
== genericMessageType);
method.MakeGenericMethod(viewModelType)
.Invoke(Messenger.Default, new [] { message, navigationToken });
}