2012-03-28 4 views
0

나는 다음과 같은 문제가 있습니다MVVM 빛 캐스팅 메시지

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를 사용하지만 나 또한 뷰 모델 객체를 (I 목록 페이지에서를 탐색하는 데 사용할 전달할 수 있도록 지원을 세부 사항 페이지 및 선택된 개체를 전달할 수)

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>으로 전송하는 것입니다. 그 주위에 방법이 있습니까?

메신저가 전송되는 실제 개체 유형을 감지하고 해당 유형에 대해 등록 된 개체로 올바르게 배달되도록 수행 할 수 있습니까?

+0

왜 작동하지 않습니까? 컴파일 오류가 발생합니까? 예외? –

+0

아니요, 간단한 메시지는 배달되지 않습니다. –

+0

올바른 유형의 메시지를 보낼 수 없습니까? –

답변

2

가능한 한 가지 방법은 런타임에 올바른 제네릭 형식으로 메시지를 작성하여 리플렉션을 사용하여 메시지를 보내는 것입니다.
또 다른 하나는 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 }); 
} 

이 코드는 NavigationTokenstring 있다고 가정합니다. 그렇지 않은 경우 Send 메소드의 두 번째 매개 변수 유형을 변경하십시오. MessengerSend 메서드의 오버로드가 하나만 포함되어있는 경우 Single의 조건을 단순화 할 수 있습니다. 다른 한편, 해당 메소드에 많은 오버로드가있는 경우이를 재정의해야 할 수도 있습니다.

+0

반사 접근법의 예를 들어 주시겠습니까? WP7을 타겟으로하고 있는데, 동적 키워드 –

+0

을 지원하지 않습니다. @ TomášBezouška : 업데이트를 참조하십시오. –

+0

a-may-zing :) 예외를 던지고 "method.MakeGenericMethod (viewModelType)"대신 "method.MakeGenericMethod (messageType)"을 사용 했으므로 Count() == 2 이후 onther 조건을 약간 수정해야했습니다.) "그리고 그것은 매력처럼 작동합니다 :) 나는 반사가 그러한 가능성을 가지고 있다는 것을 전혀 모르고있었습니다. :) –

0

메시지를 Messenger.Default.Send<NavigatingMessage<DetailViewModel>>(new NavigatingMessage<DetailViewModel>(this, PassedObject)으로 보내면 전송하지 않고 원하는대로 메시지를받을 수 있습니다.

+0

예,하지만 그 동작의 목적을 패배시킬 것입니다 - ViewModelBase –

+0

mmm에서 상속 한 객체를 보낼 수 있기를 원합니다. 그러면 캐스팅과 함께 살아야 할까봐 걱정됩니다. ( –

+0

@LOSTCODER : 그건 아니야. 맞습니다. 내 대답을 참조하십시오. 새로운 것을 배울 수도 있습니다 :-) –

0

이것은 현재 버전의 MVVM Light에 대한 제한 사항입니다. 나는 그것을 미래에 향상시킬 생각을하고 있지만 매우 까다 롭습니다 ...

+0

제 대답을보세요. 이 기능을 구현하는 데 어떤 도움이 될까요? DLR은 아주 강력합니다. –

관련 문제