【问题标题】:Get difference between Window ShowDialog cancel and close获取窗口 ShowDialog 取消和关闭之间的区别
【发布时间】:2014-12-19 13:18:54
【问题描述】:

在我们的应用程序中,我们使用 WPF 和 Caliburn Micro。我们使用自定义的 WindowManager:

public class OurWindowManager : Caliburn.Micro.WindowManager
{
    protected override Window EnsureWindow(object model, object view, bool isDialog)
    {
        var window = base.EnsureWindow(model, view, isDialog);
        if (isDialog) window.ResizeMode = ResizeMode.NoResize;
        window.Icon = new BitmapImage(new Uri("pack://application:,,,/NWB.ico"));

        // TODO: Change to dynamic minWidth/minHeight based on window
        window.MinWidth = 600;

        new WindowSettingsBehavior().Attach(window);

        return window;
    }
}

在我们的代码中,我们主要这样使用这个 WindowManager:

public void SomeMethod()
{
    var result = _windowManager.ShowDialog(new ConfirmDialogViewModel("some title",
        "some text"));
    if(result == true){ // if OK is pressed
        // do something on OK
    }
    // do nothing
}

在我最近的一种方法中,我想做以下事情(半伪代码):

public void SomeOtherMethod()
{
    _windowManager.ShowDialog(new ConfirmDialogViewModel("some title", "some text"));
    //if window is closed without pressing any of the buttons
        return; // do nothing

    //if OK is pressed {
        // do something on OK
    }
    // if Cancel is pressed: do something else
}

不幸的是,如果窗口关闭,ShowDialog 也会返回 false(即使 ShowDialog 返回 Nullable bool (bool?))。

所以,到目前为止,我所做的只是通过创建一个新的 Window-Behavior 来完全删除关闭按钮,并将其添加到 if(isDialog) 内的 OurWindowManager 类中:

if (isDialog)
{
    window.ResizeMode = ResizeMode.NoResize;
    new WindowHideBarBehavior().Attach(window);
}

这行得通,我现在得到了一个只有标题的窗口,没有关闭 (X) 按钮。不幸的是,仍然可以使用 Alt+F4 等关闭窗口。我想过抓住 Alt+F4 并取消关闭,但由于 Alt+F4 是标准的 Window 行为,我认为用户不会很欣赏它,我发现用户禁用它有点不直观..

所以,我的问题是:我怎样才能完成上面提到的SomeOtherMethod 中的伪代码。有没有办法区分关闭对话框或取消对话框。 (注意:如上所述,请记住我们使用Caliburn.Micro.WindowManager,而不是默认的 C# WPF 之一。不知道是否有很多差异,但我想至少有一些。)


编辑:

我也知道我可以捕获关闭事件并取消关闭:

window.Closing -= DisableDialogClosing;
if (isDialog)
{
    window.ResizeMode = ResizeMode.NoResize;
    new WindowHideBarBehavior().Attach(window);
    window.Closing += DisableDialogClosing;
}

...

private static void DisableDialogClosing(object sender, CancelEventArgs e)
{
    e.Cancel = true;
}

但是当我希望它关闭时它也会取消关闭(例如当按下取消/确定按钮时)。也许我可以在这个被覆盖的 Closing-EventHandler 中添加某种属性标志,但也许你们有其他建议来完成相同的结果。

【问题讨论】:

  • 我会考虑这样一个事实,如果单击取消并关闭窗口执行不同的操作,用户可能会有点不直观。
  • 在winforms中有CloseReason作为参数传递给Form.Closing,如果在wpf中没有这样的(搜索?),那么你可以在你的对话框中实现它(作为属性)。跨度>
  • @Sinatr 据我所知,WPF 中确实没有CloseReason。我自己从未使用过 Forms,但在谷歌搜索如何发现 Cancel 和 Close 之间的区别时,我确实发现了一些关于它的东西。
  • 制作枚举,制作属性ClosedBy,如果按下Cancel按钮设置ClosedBy = Cancel并关闭窗口,(对于Ok按钮-ClosedBy = Ok),默认值可以是@987654340 @(不知道如何区分 Alt-F4 和 Windows 关闭请求,但也许你不需要它)。
  • @BenRobinson 也许你是对的。现在它询问用户是否要在继续之前保存数据(是的,no 和 close 应该什么都不做/取消操作)。是否可以使用三个按钮而不是两个按钮在 ViewModel 上调用 ShowDialog(所以我的 Dialog 行为与 OurWindowManager 中添加的相同)?

标签: c# wpf dialog event-handling caliburn.micro


【解决方案1】:

如果您通过扩展Window 类来实现自己的对话框Window,就可以满足您的要求。在您的自定义Window 内部,您可以处理Closed 事件并将Window.DialogResult 属性设置为null。对于普通的OkCancel 状态,您可以简单地将Click 处理程序附加到这些Buttons 并将Window.DialogResult 属性设置为truefalse

private void CustomDialogWindow_Close(object sender, RoutedEventArgs e)
{
    DialogResult = null;
}

private void OkButton_Click(object sender, RoutedEventArgs e)
{
    DialogResult = true;
}

private void CancelButton_Click(object sender, RoutedEventArgs e)
{
    DialogResult = false;
}

然后您可以像这样检查Window 关闭状态:

if (CustomDialogWindow.DialogResult == null) DoSomethingUponDialogWindowClose();

您可以在 MSDN 的以下页面中找到更多有用的信息:

Dialog Boxes Overview
Window.DialogResult Property

【讨论】:

    【解决方案2】:

    根据@Sinatr 的建议,我在 ConfirmDialogViewModel 中添加了 ClosedBy 属性:

    (之前):

    public sealed class ConfirmDialogViewModel : Screen
    {
        public ConfirmDialogViewModel(string title, string message)
        {
            DisplayName = title;
            Message = message;
        }
    
        public string Message { get; set; }
    
        public void Ok()
        {
            TryClose(true);
        }
    
        public void Cancel()
        {
            TryClose(false);
        }
    }
    

    (之后):

    public sealed class ConfirmDialogViewModel : Screen
    {
        public ClosedBy CloseReason { get; private set; }
    
        public ConfirmDialogViewModel(string title, string message)
        {
            DisplayName = title;
            Message = message;
            CloseReason = ClosedBy.Other;
        }
    
        public string Message { get; set; }
    
        public void Ok()
        {
            CloseReason = ClosedBy.Ok;
            TryClose(true);
        }
    
        public void Cancel()
        {
            CloseReason = ClosedBy.Cancel;
            TryClose(false);
        }
    }
    
    public enum ClosedBy
    {
        Other,
        Ok,
        Cancel
    }
    

    我现在这样使用它:

    public void SomeOtherMethod()
    {
        var confirmDialog = new ConfirmDialogViewModel("some title", "some text");
        var result = _windowManager.ShowDialog(confirmDialog);
        if(result == null || confirmDialog.CloseReason == ClosedBy.Other) return;
    
        if(result == true && confirmDialog.CloseReason == ClosedBy.Ok){
            // Do something on OK
        }
        // Do something on cancel
    }
    

    我仍然保留了删除关闭按钮的行为,并且还在if(isDialog)内的OurWindowManager中添加了window.ShowInTaskbar = false;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-04
      • 1970-01-01
      • 2012-07-18
      • 1970-01-01
      • 2012-03-18
      • 2013-10-25
      相关资源
      最近更新 更多