Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cassandra/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# MVVM灯光投射消息_C#_Silverlight_Mvvm_Mvvm Light - Fatal编程技术网

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 });
}