【问题标题】:How to close dialog window from viewmodel (Caliburn+WPF)?如何从视图模型(Caliburn+WPF)关闭对话框窗口?
【发布时间】:2012-04-22 20:26:26
【问题描述】:

我有ViewModel1 和与之关联的 View1。我使用IWindowManager 对象从ViewModel2(另一个视图模型)开始对话窗口。 ViewModel2类的代码:

windowManager.ShowDialog(new ViewModel());

所以,我有 View1 用户控件的对话框窗口。

我的答案是下一个 - 我可以使用红色关闭按钮关闭该对话框窗口,但如何使用我的特定按钮(包含在View1 用户控件中)关闭它,例如带有关闭命令的“取消”按钮(@987654327 @), CancelCommand 当然包含在ViewModel1 类中。

【问题讨论】:

    标签: wpf dialog window caliburn.micro


    【解决方案1】:

    如果您的视图模型扩展 Caliburn.Micro.Screen,那就更容易了:

    TryClose();
    

    【讨论】:

    • 只有当您尝试关闭主应用程序窗口时,它才会关闭整个应用程序。
    • 嗨@MichalT,我正在显示类似于 await _dialogManager.ShowDialogAsync(item, new List() { DialogResult.Cancel }) 的对话框;我想用计时器关闭它。当我使用 this.DialogHost().TryClose(DialogResult.Cancel);然后 this.DialogHost() 给出 null。
    【解决方案2】:

    您可以通过在 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。

    【讨论】:

      【解决方案3】:

      我经常使用的一种更简洁的方式(个人喜好)是使用 IResult 模式,这样你就可以抽象 Window 实现

      视图模型

      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 注入依赖项,然后您的 VIewmodel 关闭方法将如下所示

      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);
          }
      }
      

      edit 刚刚注意到我忘记添加上述 IoC 示例的示例,这里是 使用子 IoC 容器模式,它看起来像这样

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

      如果没有子容器模式,您需要手动将父依赖注入到子容器中

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-09-23
        • 2017-06-07
        • 1970-01-01
        • 2014-09-02
        • 1970-01-01
        • 2011-11-22
        • 1970-01-01
        相关资源
        最近更新 更多