diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/AppModel/ComGuids.cs b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/AppModel/ComGuids.cs
index b6398fa0e06..28839a472fa 100644
--- a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/AppModel/ComGuids.cs
+++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/AppModel/ComGuids.cs
@@ -15,6 +15,8 @@ internal static class IID
public const string EnumObjects = "2c1c7e2e-2d0e-4059-831e-1e6f82335c2e";
/// IID_IFileDialog
public const string FileDialog = "42f85136-db7e-439c-85f1-e4075d135fc8";
+ /// IID_IFileDialog2
+ public const string FileDialog2 = "61744fc7-85b5-4791-a9b0-272276309b13";
/// IID_IFileDialogEvents
public const string FileDialogEvents = "973510DB-7D7F-452B-8975-74A85828D354";
/// IID_IFileOpenDialog
diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/AppModel/ShellProvider.cs b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/AppModel/ShellProvider.cs
index fc75ec3c999..16ddad1bebf 100644
--- a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/AppModel/ShellProvider.cs
+++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/AppModel/ShellProvider.cs
@@ -479,6 +479,72 @@ internal interface IFileDialog : IModalWindow
void SetFilter([MarshalAs(UnmanagedType.Interface)] object pFilter);
}
+ [
+ ComImport,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ Guid(IID.FileDialog2),
+ ]
+ internal interface IFileDialog2 : IFileDialog
+ {
+ #region IFileDialog redeclarations
+ #region IModalWindow redeclarations
+ [PreserveSig]
+ new HRESULT Show(IntPtr parent);
+ #endregion
+
+ new void SetFileTypes(uint cFileTypes, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] COMDLG_FILTERSPEC[] rgFilterSpec);
+
+ new void SetFileTypeIndex(uint iFileType);
+
+ new uint GetFileTypeIndex();
+
+ new uint Advise(IFileDialogEvents pfde);
+
+ new void Unadvise(uint dwCookie);
+
+ new void SetOptions(FOS fos);
+
+ new FOS GetOptions();
+
+ new void SetDefaultFolder(IShellItem psi);
+
+ new void SetFolder(IShellItem psi);
+
+ new IShellItem GetFolder();
+
+ new IShellItem GetCurrentSelection();
+
+ new void SetFileName([MarshalAs(UnmanagedType.LPWStr)] string pszName);
+
+ [return: MarshalAs(UnmanagedType.LPWStr)]
+ new string GetFileName();
+
+ new void SetTitle([MarshalAs(UnmanagedType.LPWStr)] string pszTitle);
+
+ new void SetOkButtonLabel([MarshalAs(UnmanagedType.LPWStr)] string pszText);
+
+ new void SetFileNameLabel([MarshalAs(UnmanagedType.LPWStr)] string pszLabel);
+
+ new IShellItem GetResult();
+
+ new void AddPlace(IShellItem psi, FDAP alignment);
+
+ new void SetDefaultExtension([MarshalAs(UnmanagedType.LPWStr)] string pszDefaultExtension);
+
+ new void Close([MarshalAs(UnmanagedType.Error)] int hr);
+
+ new void SetClientGuid([In] ref Guid guid);
+
+ new void ClearClientData();
+
+ new void SetFilter([MarshalAs(UnmanagedType.Interface)] object pFilter);
+ #endregion
+
+ void SetCancelButtonLabel([MarshalAs(UnmanagedType.LPWStr)] string pszLabel);
+
+ void SetNavigationRoot(IShellItem psi);
+ }
+
[
ComImport,
InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/Microsoft/Win32/CommonItemDialog.cs b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/Microsoft/Win32/CommonItemDialog.cs
index adc345abe58..e870150088c 100644
--- a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/Microsoft/Win32/CommonItemDialog.cs
+++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/Microsoft/Win32/CommonItemDialog.cs
@@ -98,6 +98,49 @@ public override string ToString()
//---------------------------------------------------
#region Public Properties
+ // FOS_DONTADDTORECENT
+ // Do not add the item being opened or saved to the recent documents list (SHAddToRecentDocs).
+ //
+ ///
+ /// Gets or sets a value indicating whether the dialog box will add the item
+ /// being opened or saved to the recent documents list.
+ ///
+ public bool AddToRecent
+ {
+ get
+ {
+ return !GetOption(FOS.DONTADDTORECENT);
+ }
+ set
+ {
+
+ SetOption(FOS.DONTADDTORECENT, !value);
+ }
+ }
+
+ ///
+ /// Gets or sets a Guid to associate with the dialog's persisted state.
+ ///
+ public Guid? ClientGuid { get; set; }
+
+ ///
+ /// Gets or sets the initial directory displayed by the file dialog box
+ /// if there is not a recently used directory value available.
+ ///
+ public string DefaultDirectory
+ {
+ get
+ {
+ // Avoid returning a null string - return String.Empty instead.
+ return _defaultDirectory.Value == null ? String.Empty : _defaultDirectory.Value;
+ }
+ set
+ {
+
+ _defaultDirectory.Value = value;
+ }
+ }
+
// The actual flag is FOS_NODEREFERENCELINKS (set = do not dereference, unset = deref) -
// while we have true = dereference and false=do not dereference. Because we expose
// the opposite of the Windows flag as a property to be clearer, we need to negate
@@ -137,6 +180,43 @@ public string InitialDirectory
}
}
+ ///
+ /// Gets or sets the initial directory displayed by the file dialog box.
+ ///
+ public string RootDirectory
+ {
+ get
+ {
+ // Avoid returning a null string - return String.Empty instead.
+ return _rootDirectory.Value == null ? String.Empty : _rootDirectory.Value;
+ }
+ set
+ {
+
+ _rootDirectory.Value = value;
+ }
+ }
+
+ // FOS_FORCESHOWHIDDEN
+ // Include hidden and system items.
+ //
+ ///
+ /// Gets or sets a value indicating whether the dialog box will show
+ /// Include hidden items regardless of user preferences.
+ ///
+ public bool ShowHiddenItems
+ {
+ get
+ {
+ return GetOption(FOS.FORCESHOWHIDDEN);
+ }
+ set
+ {
+
+ SetOption(FOS.FORCESHOWHIDDEN, value);
+ }
+ }
+
///
/// Gets or sets a string shown in the title bar of the file dialog.
/// If this property is null, a localized default from the operating
@@ -299,17 +379,43 @@ internal bool MessageBoxWithFocusRestore(string message,
private protected virtual void PrepareDialog(IFileDialog dialog)
{
+ if (ClientGuid is Guid guid)
+ {
+ dialog.SetClientGuid(ref guid);
+ }
+
+ if (!string.IsNullOrEmpty(DefaultDirectory))
+ {
+ IShellItem defaultDirectory = ShellUtil.GetShellItemForPath(DefaultDirectory);
+ if (defaultDirectory != null)
+ {
+ dialog.SetDefaultFolder(defaultDirectory);
+ }
+ }
+
if (!string.IsNullOrEmpty(InitialDirectory))
{
IShellItem initialDirectory = ShellUtil.GetShellItemForPath(InitialDirectory);
if (initialDirectory != null)
{
// Setting both of these so the dialog doesn't display errors when a remembered folder is missing.
- dialog.SetDefaultFolder(initialDirectory);
+ if (string.IsNullOrEmpty(DefaultDirectory))
+ {
+ dialog.SetDefaultFolder(initialDirectory);
+ }
dialog.SetFolder(initialDirectory);
}
}
+ if (!string.IsNullOrEmpty(RootDirectory))
+ {
+ IShellItem rootDirectory = ShellUtil.GetShellItemForPath(RootDirectory);
+ if (rootDirectory != null && dialog is IFileDialog2 dialog2)
+ {
+ dialog2.SetNavigationRoot(rootDirectory);
+ }
+ }
+
dialog.SetTitle(Title);
dialog.SetFileName(CriticalItemName);
@@ -456,9 +562,13 @@ private void Initialize()
_itemNames = null;
_title.Value = null;
_initialDirectory.Value = null;
+ _defaultDirectory.Value = null;
+ _rootDirectory.Value = null;
// Set this to an empty list so callers can simply add to it. They can also replace it wholesale.
CustomPlaces = new List();
+ ClientGuid = null;
+
}
private bool HandleItemOk(IFileDialog dialog)
@@ -667,6 +777,8 @@ void IDisposable.Dispose()
// that control the appearance of the file dialog box.
private SecurityCriticalDataForSet _title; // Title bar of the message box
private SecurityCriticalDataForSet _initialDirectory; // Starting directory
+ private SecurityCriticalDataForSet _defaultDirectory; // Starting directory if no recent
+ private SecurityCriticalDataForSet _rootDirectory; // Topmost directory
// We store the handle of the file dialog inside our class
// for a variety of purposes (like getting the title of the dialog
diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/Microsoft/Win32/OpenFileDialog.cs b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/Microsoft/Win32/OpenFileDialog.cs
index c7c00a8662c..1d2af2f29ca 100644
--- a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/Microsoft/Win32/OpenFileDialog.cs
+++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/Microsoft/Win32/OpenFileDialog.cs
@@ -155,6 +155,25 @@ public override void Reset()
//---------------------------------------------------
#region Public Properties
+ // FOS_FORCEPREVIEWPANEON
+ // Indicates to the Open dialog box that the preview pane should always be displayed.
+ //
+ ///
+ /// Gets or sets an option flag indicating whether the
+ /// dialog box forces the preview pane on.
+ ///
+ public bool ForcePreviewPane
+ {
+ get
+ {
+ return GetOption(FOS.FORCEPREVIEWPANEON);
+ }
+ set
+ {
+ SetOption(FOS.FORCEPREVIEWPANEON, value);
+ }
+ }
+
// FOS_ALLOWMULTISELECT
// Enables the user to select multiple items in the open dialog.
//
@@ -186,17 +205,7 @@ public bool Multiselect
/// Gets or sets a value indicating whether the dialog
/// contains a read-only check box.
///
- public bool ShowReadOnly
- {
- get
- {
- return _showReadOnly;
- }
- set
- {
- _showReadOnly = false;
- }
- }
+ public bool ShowReadOnly { get; set; }
#endregion Public Properties
@@ -288,9 +297,6 @@ private void Initialize()
//
//---------------------------------------------------
//#region Private Fields
-
- private bool _showReadOnly = false;
-
//#endregion Private Fields
}
}
diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/Microsoft/Win32/SaveFileDialog.cs b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/Microsoft/Win32/SaveFileDialog.cs
index 898bcc8ba3b..70b09338c25 100644
--- a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/Microsoft/Win32/SaveFileDialog.cs
+++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/Microsoft/Win32/SaveFileDialog.cs
@@ -134,6 +134,24 @@ public override void Reset()
///
public bool CreatePrompt { get; set; }
+ ///
+ /// Gets or sets a value indicating whether the dialog box will attempt to create
+ /// a test file at the selected path (default is true). If this flag is not set,
+ /// the calling application must handle errors, such as denial of access,
+ /// discovered when the item is created.
+ ///
+ public bool CreateTestFile
+ {
+ get
+ {
+ return !GetOption(FOS.NOTESTFILECREATE);
+ }
+ set
+ {
+ SetOption(FOS.NOTESTFILECREATE, !value);
+ }
+ }
+
// Causes our code to generate a message box if the selected file already
// exists. The user must confirm whether to overwrite the file.
//
diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/ref/PresentationFramework.cs b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/ref/PresentationFramework.cs
index 59f2bfc355a..7a77e13c7ba 100644
--- a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/ref/PresentationFramework.cs
+++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/ref/PresentationFramework.cs
@@ -14,9 +14,14 @@ protected virtual void CheckPermissionsToShowDialog() { }
public abstract partial class CommonItemDialog : Microsoft.Win32.CommonDialog
{
private protected CommonItemDialog() { }
+ public bool AddToRecent { get { throw null; } set { } }
+ public System.Guid? ClientGuid { get; set; }
public System.Collections.Generic.IList CustomPlaces { get { throw null; } set { } }
+ public string DefaultDirectory { get { throw null; } set { } }
public bool DereferenceLinks { get { throw null; } set { } }
public string InitialDirectory { get { throw null; } set { } }
+ public string RootDirectory { get { throw null; } set { } }
+ public bool ShowHiddenItems { get; set; }
public string Title { get { throw null; } set { } }
public bool ValidateNames { get { throw null; } set { } }
protected virtual void OnItemOk(System.ComponentModel.CancelEventArgs e) { }
@@ -73,6 +78,7 @@ public static partial class FileDialogCustomPlaces
public sealed partial class OpenFileDialog : Microsoft.Win32.FileDialog
{
public OpenFileDialog() { }
+ public bool ForcePreviewPane { get; set; }
public bool Multiselect { get { throw null; } set { } }
public System.IO.Stream OpenFile() { throw null; }
public System.IO.Stream[] OpenFiles() { throw null; }
@@ -97,6 +103,7 @@ public sealed partial class SaveFileDialog : Microsoft.Win32.FileDialog
{
public SaveFileDialog() { }
public bool CreatePrompt { get { throw null; } set { } }
+ public bool CreateTestFile { get { throw null; } set { } }
public bool OverwritePrompt { get { throw null; } set { } }
public System.IO.Stream OpenFile() { throw null; }
public override void Reset() { }