2012-06-14 142 views
0

我正在嘗試關閉它的ViewModel窗口。我正在使用MVVM模式。我已經厭倦了讓窗戶使用;WPF:從MVVM關閉一個窗口

Window parentWindow = Window.GetWindow(this); 

但我不能這樣做,我如何獲得ViewModel的窗口,所以我能夠關閉窗口。我希望能夠在代碼中做到這一點。

你能在代碼中找到父窗口嗎?

+0

可能重複: http://stackoverflow.com/questions/4376475/wpf-mvvm-how-to-close-a-window –

+1

我想發現,調用窗口的'關閉()'來自'ViewModel'的方法不是一個好的做法,並且是可控的對MVVM的想法本身也是如此。爲此目的使用觸發器。 –

回答

0

讓ViewModel這樣做,如果確實需要的話。

模型舉例說,有不再有效數據

將該信息傳遞到視圖模型

視圖模型識別,它可以不再顯示任何

,然後關閉窗口。

空視圖是表達的正常方式,有沒有更多的數據

+0

對不起,我有點困惑,我正在試圖從ViewModel中找到關閉它的窗口? – user101010101

+1

在MVVM的常規用法中ViewModel和View之間沒有直接鏈接,即不能在viewmodel中寫入類似「myWindow.Close()」的東西。但是,當然,你可以有這樣的事情。本文將引導你http://asimsajjad.blogspot.de/2010/10/closing-view-from-viewmodel-using-mvvm.html –

0

您可以在視圖模型定義操作

public Action CloseAction { get; set; } 

然後,在窗口中(例如在DataContextChanged僅)你可以設置這個動作:

((IClosable)viewModel.Content).CloseAction =() => System.Windows.Application.Current.Dispatcher.Invoke(Close()); 

那麼,這一切是一個更大的依賴注入模式的一部分,但是基本原理是在這裏... 下一頁,您有理由需要從VM調用該操作。

3

ViewModels不應以任何方式引用View,包括在MVVM中關閉窗口。

相反,ViewViewModel之間的通信通過某種事件或消息系統的典型的做法,如Microsoft Prism's EventAggregator,或MVVM Light's Messenger

例如,View應訂閱監聽CloseWindow類型的事件消息,當它收到其中一條消息時,它應該關閉。然後ViewModel只要在想要告知View關閉時隨時廣播CloseWindow消息。

有一個在MVVM事件系統,以及一些例子的簡要概述,在我的博客文章Communication between ViewModels如果你有興趣

0

有這個任務,不打破MVVM,一個行爲的有用行爲,與Expression Blend 3一起引入,允許視圖掛鉤到完全在ViewModel中定義的命令中。

這種現象說明了一個簡單的技術,以允許 視圖模型來管理一個 模型 - 視圖 - 視圖模型應用的視圖的closing事件。

這允許您在視圖(用戶控件)中掛接一個行爲,該行爲將提供對控件窗口的控制,允許ViewModel 控制是否可以通過標準ICommands關閉該窗口。

Using Behaviors to Allow the ViewModel to Manage View Lifetime in M-V-VM

http://gallery.expression.microsoft.com/WindowCloseBehavior/

1

是在視圖模型引用的觀點是不是最好的做法。爲什麼? 因爲當你單元測試你的viewmodel它需要你實例化視圖,對於小視圖來說不會那麼困難,但是對於具有複雜樹視圖的複雜視圖?那不會很好。

對我來說,通過視圖模型構造函數傳遞IInputElement是最簡單的方法。 IInputElement的好處是路由事件主幹,它具有路由事件所需的RaiseEventAddHandler方法。因此您可以自由地在應用程序中將任何視圖或視圖模型直接冒泡/隧道/指定事件,而無需額外的庫。

這裏是我的視圖模型簡化代碼,但請記住這種技術只對視圖第一種方法

public class MyViewModel : INotifyPropertyChanged 
{ 
    public static readonly RoutedEvent RequestCloseEvent = EventManager.RegisterRoutedEvent("RequestClose", 
     RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(MyViewModel)); 

    private IInputElement dispatcher; 

    public MyViewModel(IInputElement dispatcher) 
    { 
     this.dispatcher = dispatcher; 
    } 

    public void CloseApplication() 
    { 
     dispatcher.RaiseEvent(new RoutedEventArgs(RequestCloseEvent)); 
    } 
} 

對你的觀點只是

DataContext = new MyViewModel(this) 
//notice "this" on the constructor 

和根視圖(窗口)工作您的應用只需

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     AddHandler(MyViewModel.RequestCloseEvent, new RoutedEventHandler(onRequestClose)); 
    } 

    private void onRequestClose(object sender, RoutedEventArgs e) 
    { 
     if (MessageBox.Show("Are you sure you want to quit?", "Confirmation", MessageBoxButton.YesNo) == MessageBoxResult.Yes) 
     { 
      Close(); 
     } 
    } 
} 

因爲IInputElement是接口而不是類,您可以輕鬆地創建一個模擬類單元測試

var target = new MyViewModel(new DispatcherMock) 

,或者你可以使用Mock庫像RhinoMocks

進一步閱讀,你可以瞭解更多關於如何使用Routed Event