2012-04-10 47 views
19

我有ViewModel1和View1與它關聯。我使用IWindowManager對象從ViewModel2(另一個視圖模型)開始對話框窗口。從ViewModel2類代碼:如何從viewmodel(Caliburn + WPF)關閉對話窗口?

windowManager.ShowDialog(new ViewModel()); 

所以,我有對話窗口與視圖1的用戶控制。我可以使用紅色關閉按鈕關閉對話框窗口,但是如何使用我的特定按鈕(包含在View1用戶控件中)關閉它,類似於使用關閉命令(Command={Binding CancelCommand})的「取消」按鈕, CancelCommand當然包含在ViewModel1類。

回答

36

,如果您的視圖模型擴展Caliburn.Micro.Screen那就更簡單了:

TryClose(); 
+0

TryClose嘗試關閉整個應用程序... – Tim 2012-07-25 13:56:52

+16

只有當您嘗試關閉主應用程序窗口時,纔會關閉整個應用程序。 – 2012-10-04 20:51:34

+0

你剛剛救了我的日子:-) – juFo 2013-05-23 15:21:49

10

您可以在ViewModel上實現IViewAware接口來獲得當前視圖(在您的情況下是對話窗口)。然後,在執行命令時,您可以在視圖上調用Close(作爲對話框創建的Window)。

最簡單的原因是ViewAware推導:

public class DialogViewModel : ViewAware 
{ 
    public void ExecuteCancelCommand() 
    { 
     (GetView() as Window).Close(); 
    } 
} 

如果您不能得到你可以自己實現:

public class DialogViewModel : IViewAware 
{ 
    public void ExecuteCancelCommand() 
    { 
     dialogWindow.Close(); 
    } 

    private Window dialogWindow; 
    public void AttachView(object view, object context = null) 
    { 
     dialogWindow = view as Window; 
     if (ViewAttached != null) 
      ViewAttached(this, 
       new ViewAttachedEventArgs(){Context = context, View = view}); 
    } 

    public object GetView(object context = null) 
    { 
     return dialogWindow; 
    } 

    public event EventHandler<ViewAttachedEventArgs> ViewAttached; 
} 

注:我用Caliburn.Micro 1.3 .1爲我的樣品。

+0

就是這樣!非常感謝!!!)))) – 2012-04-11 07:20:48

5

一個更清潔的方式(看個人口味主題),我用了很多是使用IResult模式,這樣你抽象窗口實行

視圖模型

public IEnumerable<IResult> CloseMe() 
{ 
    yield return new CloseResult(); 
} 

結果代碼

public class CloseResult : Result 
{ 
    public override void Execute(ActionExecutionContext context) 
    { 
     var window = Window.GetWindow(context.View); 
     window.Close();    

     base.Execute(context); 
    } 
} 

public abstract class Result : IResult 
{ 
    public virtual void Execute(ActionExecutionContext context) 
    { 
     OnCompleted(this, new ResultCompletionEventArgs()); 
    } 

    protected virtual void OnCompleted(object sender, ResultCompletionEventArgs e) 
    { 
     if (Completed != null) 
      Completed(sender, e); 
    } 

    public event EventHandler<ResultCompletionEventArgs> Completed; 
} 

編輯(只有IoC需要):如果您想要更進一步,請爲所有屏幕做一個基類

public abstract class ShellPresentationModel : Screen 
{ 
    public ShellPresentationModel(IResultFactory resultFactory) 
    { 
     Result = resultFactory; 
    } 

    public IResultFactory Result { get; private set; } 
} 

這樣你就可以用的IoC注入依賴更加容易,那麼你的視圖模型close方法看起來像這樣

public IEnumerable<IResult> CloseMe() 
{ 
    yield return Result.Close(); 
} 

上使用IResult一個例子依賴性可以

public class ShowDialogResult<TModel> : Result 
{ 
    private readonly IWindowManager windowManager; 
    private readonly TModel model; 
    private Action<TModel> configure; 

    public ShowDialogResult(IWindowManager windowManager, TModel model) 
    { 
     this.windowManager = windowManager; 
     this.model = model; 
    } 

    public IResult Configure(Action<TModel> configure) 
    { 
     this.configure = configure; 
     return this; 
    } 

    public override void Execute(ActionExecutionContext context) 
    { 
     if(configure != null) 
      configure(model); 

     windowManager.ShowDialog(model); 

     base.Execute(context); 
    } 
} 

編輯只是注意到,我忘了添加上面的IoC例子的例子,這裏去 隨着兒童IoC包含它看起來像這樣

public IEnumerable<IResult> ShowDialog() 
{ 
    yield return Result.ShowDialog<MyViewModel>(); 
} 

沒有一個子容器模式ER模式,你將需要注入母公司dependeync到孩子手動

yield return Result.ShowDialog<MyViewModel>().Configure(m => m.SomeData = this.SomeData);