19

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

windowManager.ShowDialog(new ViewModel());

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

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

4

3 回答 3

44

如果您的视图模型扩展,它会更容易Caliburn.Micro.Screen

TryClose();
于 2012-07-19T20:15:47.637 回答
10

IViewAware您可以通过在 ViewModel 上实现接口来获取当前视图(在您的情况下为对话框窗口) 。然后,您可以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。

于 2012-04-10T16:30:11.603 回答
5

我经常使用的一种更简洁的方法(个人喜好的主题)是使用 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);
    }
}

编辑刚刚注意到我忘记添加上述 IoC 示例的示例,这里有一个子 IoC 容器模式,它看起来像这样

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

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

    yield return Result.ShowDialog<MyViewModel>().Configure(m => m.SomeData = this.SomeData);
于 2012-04-16T13:38:04.180 回答