我有以下行为:
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));
...
}它基本上使用NavigateToPageAction (在Blend中也有),但也允许我广播一个ViewModel对象(我使用它在列表页面到详细页面之间导航,并传递选定的对象)
Xaml将如下所示:( PassedObject绑定到从ViewModelBase继承的DetailViewModel实例)
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonDown">
<b:NavigateAndBroadcastAction TargetPage="/View/SubjectDetailPage.xaml" NavigationToken="SubjectDetailNavigationToken" PassedObject="{Binding}" />
</i:EventTrigger>
</i:Interaction.Triggers>现在,我想注册这条消息:
Messenger.Default.Register<NavigatingMessage<DetailViewModel>>(this, NavigationToken, true, Action);但这并不管用。真正起作用的是注册NavigatingMessage<ViewModelBase>,然后将接收到的消息转换为NavigatingMessage<DetailViewModel>。有没有办法绕过这一点?
是否可以这样做,以便信使检测正在发送的对象的实际类型,并正确地将其传递到为该类型注册的对象?
发布于 2012-03-28 19:32:35
一种可能的方法是使用反射发送消息,方法是在运行时创建具有正确泛型类型的消息。
另一种方法是使用dynamic和类型推断:
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(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 });
}这段代码假设NavigationToken是一个string。如果没有,只需更改Send方法的第二个参数的类型。如果Messenger只包含Send方法的一个重载,则可以简化Single中的条件。另一方面,如果该方法有很多重载,您可能需要对其进行改进。
发布于 2012-03-28 19:17:44
如果你以Messenger.Default.Send<NavigatingMessage<DetailViewModel>>(new NavigatingMessage<DetailViewModel>(this, PassedObject)的形式发送消息,你将能够接收到你想要的消息,而不需要强制转换。
发布于 2012-03-28 19:34:09
这是MVVM Light当前版本的一个限制。我正在考虑在未来改进这一点,但这是相当棘手的…
https://stackoverflow.com/questions/9906024
复制相似问题