2015-02-09 71 views
0

我需要根據在窗口中顯示的控件中觸發的單擊命令從ViewModel關閉模態窗口。WPF和MVVM - 從子窗口內關閉窗口

所以,我有MainViewModel,JimViewModel,JimWindow和JimControl。 MainViewModel創建一個JimWindow並將其DataContext設置爲JimViewModel。 JimWindow包含JimControl,其中包含一個按鈕。點擊這個按鈕時,我想觸發一個以某種方式關閉JimWindow的命令。

我已經看到了幾個問題,回答這關於從實際窗口關閉窗口(通過將窗口的實例傳遞給ViewModel上的命令),但它並沒有轉化爲我想要的去做。

我沒有使用框架,所以我沒有方便的使者來幫助我。誰能幫忙?是否以某種方式引用控件的父窗口的名稱?

+0

自閉窗是嚴格觀點有關,我要說重寫事件調用命令(如果必要的話)並關閉窗口比在命令中提供該功能的視圖模型更好。 – chris 2015-02-09 16:32:38

+0

但是這個電話會在哪裏結束?關閉窗口的按鈕位於窗口內的控件中。窗戶是否應該將自己的參照傳遞給控制? – jimbo 2015-02-09 16:39:04

+0

函數將在窗口的上下文中被覆蓋。也就是說,重寫的類將是窗口,因此可以調用'Close()'。這將代碼添加到代碼應該稀缺的地方,但我不認爲它是屬於VM的代碼。我沒有足夠的經驗來了解所有其他可用選項。 – chris 2015-02-09 16:41:50

回答

1

MainViewModel不應該創建窗口,至少不是直接。虛擬機只能創建虛擬機。窗戶是視野的一部分。

如果您需要在一個窗口中託管JimVM,那麼最好是將某種WindowService抽象出一個接口。 MainVM然後只是創建JimVM,並將其提供給窗口服務,以在窗口中主機

一旦你已經將Windows位分離成一個單獨的服務,那麼你可以在那裏做所有的crufty窗口的東西。我會有JimVM公開CloseCommandClosed事件。您可以將您的JimControl按鈕綁定到CloseCommand,並且Windows服務可以訂閱Close事件,並在觸發時拆除窗口。

這使視圖和虛擬機的東西完全分離。唯一知道如何將兩者粘合在一起的是窗口管理器。

0

儘管ViewModel創建View的想法聽起來有點向後,但您可以使用消息傳遞,例如, TinyMessengerMVVMLight附帶的Messenger。

然後,您可以在View/ViewModel中註冊消息並從任何地方發送消息。使用MVVMLight一個非常簡單的例子是:

// custom message 
public class CloseMessage : MessageBase 
{ 
    public CloseMessage(object sender) 
     :base(sender) 
    {} 
} 

// main view registers for a message 
public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     Messenger.Default.Register<CloseMessage>(this, message => 
     { 
      // do teh stuff 
     }); 
    } 
    ... 
} 

// command bound to close button sends the message 
private void YourCloseMainViewCommand() 
{ 
    Messenger.Default.Send(new CloseMessage(this)); 
} 
+0

我不確定我關注。我對Messenger類沒有太多瞭解。將JimWindow創建爲我的MainWindow(或者說,在我的情況下是MainControl)類中的一個實例嗎? – jimbo 2015-02-10 07:41:35

+0

它甚至沒有關係。您可以隨時註冊/發送消息。 – 2015-02-10 07:43:27

+1

其實我有一箇舊回購搭建示範MVVM消息在https://github.com/mikkoviitala/cross-viewmodel-communication,如果你想看一看。 – 2015-02-10 07:47:58