首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MVVM轻量投射消息

MVVM轻量投射消息
EN

Stack Overflow用户
提问于 2012-03-28 18:55:24
回答 3查看 438关注 0票数 0

我有以下行为:

代码语言:javascript
复制
    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实例)

代码语言:javascript
复制
<i:Interaction.Triggers>
     <i:EventTrigger EventName="MouseLeftButtonDown">
         <b:NavigateAndBroadcastAction TargetPage="/View/SubjectDetailPage.xaml" NavigationToken="SubjectDetailNavigationToken" PassedObject="{Binding}" />
     </i:EventTrigger>
</i:Interaction.Triggers>

现在,我想注册这条消息:

代码语言:javascript
复制
Messenger.Default.Register<NavigatingMessage<DetailViewModel>>(this, NavigationToken, true, Action);

但这并不管用。真正起作用的是注册NavigatingMessage<ViewModelBase>,然后将接收到的消息转换为NavigatingMessage<DetailViewModel>。有没有办法绕过这一点?

是否可以这样做,以便信使检测正在发送的对象的实际类型,并正确地将其传递到为该类型注册的对象?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-03-28 19:32:35

一种可能的方法是使用反射发送消息,方法是在运行时创建具有正确泛型类型的消息。

另一种方法是使用dynamic和类型推断:

代码语言:javascript
复制
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);
}

使用反射的版本有点混乱:

代码语言:javascript
复制
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中的条件。另一方面,如果该方法有很多重载,您可能需要对其进行改进。

票数 2
EN

Stack Overflow用户

发布于 2012-03-28 19:17:44

如果你以Messenger.Default.Send<NavigatingMessage<DetailViewModel>>(new NavigatingMessage<DetailViewModel>(this, PassedObject)的形式发送消息,你将能够接收到你想要的消息,而不需要强制转换。

票数 0
EN

Stack Overflow用户

发布于 2012-03-28 19:34:09

这是MVVM Light当前版本的一个限制。我正在考虑在未来改进这一点,但这是相当棘手的…

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9906024

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档