如何从viewmodel(Caliburn&x2B;WPF)关闭对话框窗口?

如何从viewmodel(Caliburn&x2B;WPF)关闭对话框窗口?,wpf,dialog,window,caliburn.micro,Wpf,Dialog,Window,Caliburn.micro,我有与其关联的ViewModel1和View1。我使用IWindowManager对象从ViewModel2(另一个视图模型)启动对话框窗口。ViewModel2class中的代码: windowManager.ShowDialog(new ViewModel()); 因此,我有一个带有View1用户控件的对话框窗口 我的答案是下一步-我可以使用红色关闭按钮关闭该对话框窗口,但如何使用我的特定按钮(包含在View1用户控件中)关闭它,类似于带有关闭命令的“取消”按钮(command={Bind

我有与其关联的
ViewModel1
和View1。我使用
IWindowManager
对象从
ViewModel2
(另一个视图模型)启动对话框窗口。
ViewModel2
class中的代码:

windowManager.ShowDialog(new ViewModel());
因此,我有一个带有View1用户控件的对话框窗口


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

通过在ViewModel上实现
IViewAware
界面,可以获得当前视图(在您的情况下是对话框窗口)。然后,在执行命令时,可以在视图上调用
Close
(创建为对话框的
窗口)

最简单的原因是从
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;
}
公共类对话框viewmodel:IViewAware
{
public void ExecuteCancelCommand()
{
dialogWindow.Close();
}
私人窗口;
public void AttachView(对象视图,对象上下文=null)
{
dialogWindow=作为窗口查看;
如果(ViewAttached!=null)
附件(本、,
新建ViewAttachedEventArgs(){Context=Context,View=View});
}
公共对象GetView(对象上下文=null)
{
返回对话框窗口;
}
公共事件事件处理程序ViewAttached;
}
注意:我的示例使用了Caliburn.Micro 1.3.1。

我经常使用的一种更干净的方式(个人喜好的主题)是使用IResult模式,这样您就可以抽象窗口实现

视图模型

public IEnumerable<IResult> CloseMe()
{
    yield return new CloseResult();
}
通过这种方式,您可以更轻松地使用IoC注入依赖项,然后VIewmodel close方法将如下所示

public IEnumerable<IResult> CloseMe()
{
    yield return Result.Close();
}
public IEnumerable<IResult> ShowDialog()
{
    yield return Result.ShowDialog<MyViewModel>();
}
public IEnumerable CloseMe()
{
产生返回结果。关闭();
}
使用依赖关系的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);
    }
}
公共类ShowDialogResult:结果
{
专用只读iWindows管理器windowManager;
私有只读TModel模型;
私人行动配置;
public ShowDialogResult(IWindowManager windowManager,TModel模型)
{
this.windowManager=windowManager;
this.model=模型;
}
公共IResult配置(操作配置)
{
this.configure=configure;
归还这个;
}
公共覆盖无效执行(ActionExecutionContext上下文)
{
如果(配置!=null)
配置(模型);
windowManager.ShowDialog(模型);
base.Execute(上下文);
}
}
编辑刚刚注意到我忘了添加上述IoC exmaple的示例,如下所示 对于子IoC容器模式,它将如下所示

public IEnumerable<IResult> CloseMe()
{
    yield return Result.Close();
}
public IEnumerable<IResult> ShowDialog()
{
    yield return Result.ShowDialog<MyViewModel>();
}
public IEnumerable ShowDialog()
{
产生返回结果。ShowDialog();
}
如果没有子容器模式,则需要手动将父dependeync注入子容器

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

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

TryClose();

只有当您试图关闭主应用程序窗口时,它才会关闭整个应用程序。您好@MichalT,我显示的对话框类似于wait _dialogManager.ShowDialogAsync(item,new List(){DialogResult.Cancel});我想用定时器关闭它。使用此.DialogHost().TryClose(DialogResult.Cancel)时的内部勾号事件;然后,这个.DialogHost()给出了null。