【问题标题】:A WPF/Prism window calling CommonOpenFileDialog (select directory) loses focus after selection调用 CommonOpenFileDialog(选择目录)的 WPF/Prism 窗口在选择后失去焦点
【发布时间】:2016-10-18 15:08:52
【问题描述】:

我有一个需要“选择目录”功能的 WPF (Prism) 应用程序。主窗口的菜单通过臭名昭著的 Prism InteractionRequest 打开一个子“设置”窗口。那个“设置”窗口有一个按钮可以打开一个“选择目录”窗口。

由于标准的FolderBrowserDialog 对话框非常丑陋,我尝试使用Windows API Code Pack 中的CommonOpenFileDialog

我使用来自Orc.Controls 的服务来包装对话框:

using Microsoft.WindowsAPICodePack.Dialogs;

public class MicrosoftApiSelectDirectoryService : ISelectDirectoryService
{
    public bool DetermineDirectory()
    {
        var browserDialog = new CommonOpenFileDialog();
        browserDialog.IsFolderPicker = true;
        browserDialog.Title = Title;
        browserDialog.InitialDirectory = InitialDirectory;

        if (browserDialog.ShowDialog() == CommonFileDialogResult.Ok)
        {
            DirectoryName = browserDialog.FileName;
            return true;
        }

        DirectoryName = string.Empty;
        return false;
    }
// ...
}

在我的视图模型中,我调用_selectDirectoryService.DetermineDirectory()

    public DelegateCommand SelectDirectoryCommand { get; private set; }

    private void SelectDirectory()
    {
        if (_selectDirectoryService.DetermineDirectory())
        {
            var dir = _selectDirectoryService.DirectoryName;
            // ...
        }
    }

问题是在CommonOpenFileDialog 中选择目录后,“设置”窗口失去焦点(并且由于某种原因实际上隐藏在最大化的主窗口后面)。相比之下,FolderBrowserDialog 将焦点返回到“设置”窗口。

所以,基本上我需要更好的“选择目录”实现,或者我需要找到一种方法来再次聚焦“设置”窗口,而不会严重违反 MVVM 模式。任何想法将不胜感激。

【问题讨论】:

  • 创建自己的目录浏览器需要做很多工作,特别是如果您希望它具有 Windows 文件浏览器的所有功能。所以我建议不要这样做。对我来说,我将 DirectoryBrowser 视为 UI 控件和应用程序 UI 层的一部分,因此我的相关代码通常位于 View 的代码隐藏中。这是你的选择吗?在我看来,设置焦点也是 View 层的职责。如果你真的认为它是 ViewModel 层的一部分,我建议使用某种 DialogService 在 View 中正确显示/隐藏对话框

标签: wpf mvvm prism windows-api-code-pack


【解决方案1】:

您必须设置 Window 的父级/所有者,以防止它突然弹出。

【讨论】:

  • 什么意思?主窗口通过prism:InteractionRequestTrigger(prism:PopupWindowAction)打开“设置”窗口。 “设置”窗口通过调用服务的命令打开 CommonOpenFileDialog。但是 CommonOpenFileDialog 在关闭时不会将焦点返回到“设置”窗口。
  • 我的意思是我说的。您需要修改您的服务以设置对话窗口的所有者。
  • 作为一个肮脏的黑客,我在后面放了一些代码: Window parentWindow = Window.GetWindow(this); if (browserDialog.ShowDialog(parentWindow) == CommonFileDialogResult.Ok) { profileDirectory.Text = browserDialog.FileName; // ..;它有点解决了失去焦点的问题,但违反了 MVVM。我想知道是否有更好的方法将父窗口句柄传递给服务。
猜你喜欢
  • 1970-01-01
  • 2011-10-09
  • 2012-11-05
  • 1970-01-01
  • 2012-07-19
  • 1970-01-01
  • 2016-03-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多