SaveFileDialog 在类型更改时导航到文件夹

SaveFileDialog Navigate to Folder on Type Change

我正在尝试复制 Microsoft Word 中“保存文件”对话框的某些行为。在 Word(Office 365 最新版本)中,如果您转到“另存为”并打开浏览对话框,默认目录是“我的文档”,如果您随后将“另存为”类型更改为 "Word Template (*.dotx)",这会自动将您带到 "Custom Office Templates" 文件夹。这是我想要复制的行为。

据我所知,这在使用 Microsoft.Win32.SaveFileDialog 的 WPF 中是不可能的,如有不妥请指正。

所以我尝试使用 Microsoft.WindowsAPICodePack.Shell Nuget 包中的 CommonSaveFileDialog。我相信我已经很接近了,但我似乎无法在更改类型时让它真正执行导航部分。请参阅下面的代码,非常感谢任何建议。我需要这个用于 WPF 桌面应用程序。

CommonSaveFileDialog saveDialog;
private void Button_Click(object sender, RoutedEventArgs e)
{
    saveDialog = new CommonSaveFileDialog();
    saveDialog.Filters.Add(new CommonFileDialogFilter("My File", ".mf"));
    saveDialog.Filters.Add(new CommonFileDialogFilter("My Template File", ".mft"));

    saveDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);

    saveDialog.FileTypeChanged += saveDialog_FileTypeChanged;

    saveDialog.ShowDialog();
}

private void saveDialog_FileTypeChanged(object sender, EventArgs e)
{
    var selectedSaveAsType = saveDialog.Filters[saveDialog.SelectedFileTypeIndex - 1];

    if (selectedSaveAsType.DisplayName == "My Template File (*.mft)")
    {   
        //These don't cause a navigation... How can I achieve this?
        //saveDialog.InitialDirectory = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "My Application Templates");
        //saveDialog.DefaultDirectory = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "My Application Templates");
    } 
    else
    {
        //saveDialog.DefaultDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
    }
}

如果您需要任何进一步的信息,请告诉我。预先感谢您的任何建议。 :)

似乎没有任何 .CurrentDirectory 或 .Path 属性。或者任何类型的导航方法。

似乎 CommonSaveFileDialog 没有公开任何让您设置当前目录的属性 - 至少我找不到。

如果你真的想这样做,你可能需要深入挖掘。 CommonSaveFileDialog 在内部使用原生 Common Dialog Box Library可能 有一种方法可以让你在那个级别上做你想做的事,你必须仔细阅读文档。如果是这样,您可以直接调用它 p/invoke 样式。

搜索某种排序方法/属性 使用 .GetType().GetMethods() 更改文件夹后,仍然没有任何结果。所以我使用 dnSpy 反编译了 DLL,这导致我在 IFileDialog 中找到了一个 SetFolder 方法。

[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void SetFolder([In, MarshalAs(UnmanagedType.Interface)] IShellItem psi);

我实现目标的唯一方法是克隆 Nuget 包的 GitHub 存储库并自己添加到其中。我将以下 public 方法添加到 CommonFileDialog class.

public void SetFolder(string folderPath)
{
    // Create a native shellitem from our path
    // Add some proper error handling to ensure directory exists....
    Guid guid = new Guid(ShellIIDGuid.IShellItem2);
    IShellItem2 defaultDirectoryShellItem;
    ShellNativeMethods.SHCreateItemFromParsingName(folderPath, IntPtr.Zero, ref guid, out defaultDirectoryShellItem);
    nativeDialog.SetFolder(defaultDirectoryShellItem);
}

然后我只需调用

就可以在我的应用程序中使用它
dialog.SetFolder(@"C:\");