2012-05-28 128 views
3

我目前正在嘗試進入WPF和MVVM,但最近遇到了一個我不知道如何解決的問題。我對此很陌生,所以如果事情不是應該的,請告訴我。將對象從父視圖傳遞到MVVM中的子視圖

我有一個ParentView和它的ParentViewModel。 ParentView擁有兩個視圖SubViewA和SubViewB,它們都有自己的ViewModels。這是我的ParentView.xaml:

<local:ViewBase.DataContext> 
    <local:ParentViewModel x:Name="Model" /> 
</local:ViewBase.DataContext> 

<Grid> 
    <local:SubViewA Visibility="{Binding ElementName=Model, Path=SubViewAVisibility}" /> 
    <local:SubViewB Visibility="{Binding ElementName=Model, Path=SubViewBVisibility}" /> 
</Grid> 

我想要做的:SubViewModelB有一個屬性綁定到SubViewB。我想在ParentViewModel中發生某個事件時更改該屬性。我想這應該通過將SubViewModelB中的屬性綁定到ParentViewModel中的屬性來完成,但是我不太確定如何?我想是這樣的ParentView.xaml如下:

<local:SubViewB Visibility="{Binding ElementName=Model, Path=SubViewBVisibility}" SomeProperty="{Binding ElementName=Model, Path=WhatIWantThePropertyToBe}" /> 

但我並沒有好處。 那麼我該如何解決這個問題?我知道我可以通過MVVM輕量級工具箱中的消息來做到這一點,但這似乎與我正在嘗試做的事情不相稱。有什麼建議麼?

感謝

回答

3

聽起來像一個很好的解決了這個EventAggregator模式。有一些偉大的實現在那裏比如由Microsoft PrismTinyMessenger(非常輕巧)

作爲一個代碼示例,你會做這樣的事情提供(使用棱鏡,未測試的代碼)

public class ParentViewModel 
{ 
    private IEventAggregator eventAggregator; 

    public ParentViewModel(IEventAggregator eventAggregator) 
    { 
     this.eventAggregator = eventAggregator; 
    } 

    public void PublishSomeEvent() 
    { 
     // When a condition occurs, publish an event any subscribers 
     // that may be listening 
     this.eventAggregator.GetEvent<SomeEvent>() 
      .Publish(new SomeEvent("Hello World!"))); 
    } 
} 

public class SubViewModel 
{ 
    private IEventAggregator eventAggregator; 

    public SubViewModel(IEventAggregator eventAggregator) 
    { 
     eventAggregator.GetEvent<SomeEvent>.SomeEvent(OnSomeEventOccurred); 
    } 

    public void OnSomeEventOccurred(SomeEvent arg) 
    { 
     // This method called when ParentViewModel publishes the event 
     Console.WriteLine(arg.OptionalMessage); 
    } 
} 

您需要一個單獨的事件聲明。例如,我用這個

public SomeEvent : CompositePresentationEvent<SomeEvent> 
{ 
    public SomeEvent(string optionalMessage) 
    { 
     this.optionalMessage = optionalMessage; 
    } 

    public string OptionalMessage { get { return optionalMessage; } } 
} 
+2

謝謝!我想我可以這樣做,但這真的是正確的做法嗎?對於實際耦合的問題,它似乎是一個非常解耦的解決方案。例如,如果我有多個父視圖,並且每個都有自己的子視圖,則此解決方案將無法工作,對嗎?但我只有一個ParentView,所以我想這應該沒問題:-)謝謝! – BlackWolf

+0

這是要走的路。僅僅因爲他們是SubView並不意味着他們需要了解他們的ParentView。 對於多個ParentView,您可以讓ParentView傳遞一個Guid或某種標識符給它的SubViews,它也作爲觸發事件的一部分傳遞。然後他們所需要做的就是檢查該標識符以查看被觸發的事件是否適合他們。 –

+0

乾杯克里斯:)是的馬里奧事件聚合/經紀人是一個夢幻般的模式。結合依賴注入,它確實使生活變得輕鬆。如果你只是想輕量級,我會去與TinyMessenger。它是一個單獨的cs文件,我已經在生產系統中成功地使用了它 –

1

您將有SubViewModel比如在你的ParentViewModel吧?如果你這樣做,那麼你可以簡單地在ParentViewModel中捕獲事件並手動更改SubViewModel的特定屬性值。

我不確定這是否是完美的方式,但這應該做的工作。

另一種方式可能是子視圖的屬性直接綁定與財產ParentViewModel

嘗試是這樣的

Binding="{Binding RelativeSource={RelativeSource FindAncestor, 
AncestorType={x:Type Window}}, Path=DataContext.ParentViewModelProperty}" 
+0

感謝您的迴應。不幸的是,我沒有直接訪問SubViewModel。我的視圖自己創建他們的模型。我認爲這是MVVM中合適的方式,而且它似乎是視圖與其視圖模型之間存在明確關係的唯一途徑。 – BlackWolf

+0

查看更新的答案,它可能有幫助 –

+1

謝謝。爲Messenger的方法,但仍然有幫助。 – BlackWolf

相關問題