Closed ghost closed 2 years ago
ShareAware
Controls whether the application is called back for guidance in the case of a sharing violation.
https://user-images.githubusercontent.com/5017479/137435623-d94562f7-7c57-4e88-9464-c2b3ecfebd0a.mp4
I forgot to demonstrate that the full path of the file involved in the sharing violation is also passed back to the application.
An example of the full path passed back to the application. The application can respond to the sharing violation by handling the ShareViolation event and specifying a response of Default, Accept, or Refuse.
This is where things really got interesting and I realized that some of the file dialog events have not yet been implemented. This might be a good time to explore the FolderChange, FolderChanging, Overwrite, SelectionChange, ShareViolation, and TypeChange events.
https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nn-shobjidl_core-ifiledialogevents
Before I forget I would like to take a moment and say thank you to the Windows Forms team for making this project available on GitHub. Regardless of what happens with this proposal, this has been a wonderful learning experience that I will never forget.
FolderChanging
Occurs just before the user navigates to a new folder.
Allows the application to prevent navigation to a particular location and provides an option to redirect to an alternate folder.
https://user-images.githubusercontent.com/5017479/137570458-d0261f75-aac7-4804-b374-cb44a74f7b00.mp4
FolderChanging sample usage.
private void OpenFileDialog1_FolderChanging(object? sender, FolderChangingEventArgs e)
{
if (new DirectoryInfo(e.Folder).Name == "ForbiddenFolder")
{
// Prevent navigation to ForbiddenFolder.
e.Prevent = true;
// Redirect to recent.
e.Folder = Environment.GetFolderPath(Environment.SpecialFolder.Recent);
// Explain the restriction because the docs say to do so.
MessageBox.Show(
"This is a forbidden folder.",
"Hello WinForms", MessageBoxButtons.OK,
MessageBoxIcon.Stop);
}
}
Overwrite
Called from the save dialog when the user chooses to overwrite a file.
Allows the application to create custom overwrite prompts.
https://user-images.githubusercontent.com/5017479/137576966-66aaa263-d061-4a06-aec3-53d4e20f5bae.mp4
Overwrite sample usage.
private void SaveFileDialog1_Overwrite(object? sender, OverwriteEventArgs e)
{
// Show the overwrite prompt
DialogResult overwriteResult =
MessageBox.Show(
Path.GetFileName(e.FileName) + " already exists." +
Environment.NewLine +
"Would you like to replace it?",
"Hello WinForms", MessageBoxButtons.YesNo,
MessageBoxIcon.Exclamation);
// Set the overwrite response
e.Response = overwriteResult switch
{
DialogResult.Yes => OverwriteResponse.ACCEPT,
DialogResult.No => OverwriteResponse.REFUSE,
_ => OverwriteResponse.DEFAULT
};
}
I didn't know custom overwrite prompts were even possible.
I have noticed more file dialog features that have not been implemented yet. IFileDialogCustomize exposes methods that allows the application to add controls to the dialogs and IFileDialogControlEvents allows the application to be notified of the events related to the controls that have been added. Interesting.
I'm not ready to investigate this one yet but noting it here so I don't forget. Customized file dialogs.
I've just discovered there is more to the ShareAware/ShareViolation feature. There might be an opportunity to pass more ShareViolationEventArgs
back to the application and enable even more functionality like switching to the application that has the file open and closing the file in use from the File In Use dialog. I need to take a closer look at IFileIsInUse.
This is where things really got interesting and I realized that some of the file dialog events have not yet been implemented. This might be a good time to explore the FolderChange, FolderChanging, Overwrite, SelectionChange, ShareViolation, and TypeChange events.
docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nn-shobjidl_core-ifiledialogevents
This is awesome! If I may suggest though, let's try to concentrate on OFN_* flags here. Otherwise we risk expanding the scope beyond reason. Please open a new proposal for the events, and others (if desired/necessary) for other customisations. This way it would be easier to review and discuss each aspect individually.
Will do and thank you for clarifying that for me. If the focus of this proposal is primarily the missing file dialog options, then I'm ready to update the proposal now. I'll need a little time to sort some of it out but I'll try to be quick about it.
I've just updated the proposal above. If you need anything or have any questions please let me know. Thanks for the opportunity to take a look at this. Its been really fun.
Can you please add xml-docs for each new property explaining the purpose and denoting default values?
Good idea, done. I hope the summaries with the videos are good enough to understand.
Thank you. The team is currently super busy wrapping up .NET 6.0 and VS 2022 releases, and it will take us sometime to review the proposal (a cursory look tells me we'd want to tweak the proposed names). Please bear with us.
@willibrandon, This is still on our radar. Team is still wrapping few things in .NET 6.0 and VS releases and should be able to take this further by end of this month.
@dreddy-work, thanks for the update, looking forward to it and good luck.
I've reviewed the proposal, and compared it against the existing API. I'm proposing few tweaks:
namespace System.Windows.Forms
{
public partial class FileDialog
{
/// <summary>
- /// Controls whether to add the file being opened or saved to the recent list.
+ /// Gets or sets a value indicating whether the dialog box adds the file being opened or saved to the recent list.
/// </summary>
[DefaultValue(true)]
- public bool AddToRecent { get; set; }
+ public bool AddToRecent { get; set; } = true;
/// <summary>
- /// Controls whether to include hidden and system items.
+ /// Gets or sets a value indicating whether the dialog box displays hidden and system files.
/// </summary>
[DefaultValue(false)]
- public bool ForceShowHiden { get; set; }
+ public bool ShowHiddenFiles { get; set; }
/// <summary>
- /// Controls whether the items shown by default in the view's navigation pane are hidden.
+ /// Gets or sets a value indicating whether the items shown by default in the view's navigation pane are hidden.
/// </summary>
- [DefaultValue(false)]
- public bool HidePinnedPlaces { get; set; }
+ [DefaultValue(true)]
+ public bool ShowPinnedPlaces { get; set; } = true;
/// <summary>
- /// Controls whether the OK button needs interaction before it is enabled.
+ /// Gets or sets a value indicating whether the OK button of the dialog box is disabled until the user navigates the view or edits the filename (if applicable).
/// </summary>
+ /// <remarks>
+ /// Note: Disabling of the OK button does not prevent the dialog from being submitted by the Enter key.
+ /// </remarks>
[DefaultValue(false)]
- public bool OkButtonNeedsInteraction { get; set; }
+ public bool OkRequiresInteraction { get; set; }
}
}
namespace System.Windows.Forms
{
public partial class OpenFileDialog
{
/// <summary>
- /// Controls whether to always display the Open dialog box preview pane.
+ /// Gets or sets a value indicating whether the dialog box shows a preview for selected files.
/// </summary>
[DefaultValue(false)]
- public bool ForcePreviewPaneOn { get; set; }
+ public bool ShowPreview { get; set; }
/// <summary>
- /// Controls whether read-only items are returned.
+ /// Gets or sets a value indicating whether the dialog box allows to select read-only files.
/// </summary>
[DefaultValue(true)]
- public bool ReadOnlyReturn { get; set; }
+ public bool IgnoreReadOnly { get; set; } = true;
}
}
namespace System.Windows.Forms
{
public partial class SaveFileDialog
{
/// <summary>
- /// Controls whether to always open the Save As dialog box in expanded mode.
+ /// Gets or sets a value indicating whether the dialog box is always opened in the expanded mode.
/// </summary>
[DefaultValue(true)]
- public bool ExpandedMode { get; set; }
+ public bool ExpandedMode { get; set; } = true;
/// <summary>
- /// Controls whether to create a test file.
+ /// Gets or sets a value indicating whether the dialog box verifies whether creation of the specified file will be successful.
+ /// If this flag is not set, the calling application must handle errors, such as denial of access, discovered when the item is created.
/// </summary>
[DefaultValue(true)] <-- what's the default behaviour now?
- public bool TestFileCreate { get; set; }
+ public bool CheckWriteAccess { get; set; }
}
}
namespace System.Windows.Forms
{
public partial class FolderBrowserDialog
{
/// <summary>
- /// Controls whether to add the folder being selected to the recent list.
+ /// Gets or sets a value indicating whether the dialog box adds the folder being selected to the recent list.
/// </summary>
[DefaultValue(true)]
- public bool AddToRecent { get; set; }
+ public bool AddToRecent { get; set; } = true;
/// <summary>
- /// Controls whether to include hidden and system items.
+ /// Gets or sets a value indicating whether the dialog box displays hidden and system files.
/// </summary>
[DefaultValue(false)]
- public bool ForceShowHiden { get; set; }
+ public bool ShowHiddenFiles { get; set; }
/// <summary>
- /// Controls whether the items shown by default in the view's navigation pane are hidden.
+ /// Gets or sets a value indicating whether the items shown by default in the view's navigation pane are hidden.
/// </summary>
- [DefaultValue(false)]
- public bool HidePinnedPlaces { get; set; }
+ [DefaultValue(true)]
+ public bool ShowPinnedPlaces { get; set; } = true;
/// <summary>
- /// Controls whether the OK button needs interaction before it is enabled.
+ /// Gets or sets a value indicating whether the OK button of the dialog box is disabled until the user navigates the view or edits the filename (if applicable).
/// </summary>
+ /// <remarks>
+ /// Note: Disabling of the OK button does not prevent the dialog from being submitted by the Enter key.
+ /// </remarks>
[DefaultValue(false)]
- public bool OkButtonNeedsInteraction { get; set; }
+ public bool OkRequiresInteraction { get; set; }
}
}
I'm a little ensure about the proposed default value for the TestFileCreate
- what's the current implementation's behaviour?
[DefaultValue(true)]
public bool TestFileCreate { get; set; }
Please let me know if you have any questions or objections. If not, please update your proposal, and then I think we'll be ready to pass it on to the API Review Board. Thanks
Those tweaks look good to me, thanks for taking a look. The proposed default value for TestFileCreate
, or CheckWriteAccess
should be true which is the current default behavior. I'll update the proposal with your suggestions and if you have any other thoughts on CheckWriteAccess
please let me know.
The proposal has been updated and thank you for the suggestions @RussKie.
Thank you. Marking as ready for review by the API Review Board. The review may take awhile, once the proposal is reviewed a member of the ARB will post here.
OpenFileDialog
and SaveFileDialog
)?namespace System.Windows.Forms
{
public partial class FileDialog
{
[DefaultValue(true)]
public bool AddToRecent { get; set; } = true;
[DefaultValue(false)]
public bool ShowHiddenFiles { get; set; }
[DefaultValue(true)]
public bool ShowPinnedPlaces { get; set; } = true;
[DefaultValue(false)]
public bool OkRequiresInteraction { get; set; }
}
public partial class OpenFileDialog
{
[DefaultValue(false)]
public bool ShowPreview { get; set; }
[DefaultValue(false)]
public bool SelectReadOnly { get; set; }
}
public partial class SaveFileDialog
{
[DefaultValue(true)]
public bool ExpandedMode { get; set; } = true;
[DefaultValue(true)]
public bool CheckWriteAccess { get; set; } = true;
}
public partial class FolderBrowserDialog
{
[DefaultValue(true)]
public bool AddToRecent { get; set; } = true;
[DefaultValue(false)]
public bool ShowHiddenFiles { get; set; }
[DefaultValue(true)]
public bool ShowPinnedPlaces { get; set; } = true;
[DefaultValue(false)]
public bool OkRequiresInteraction { get; set; }
}
}
Thank you @terrajobst. @willibrandon would you like to submit a PR with an implementation?
Yes!
I can investigate replicating these in WPF.
Great! Though I suggest to raise an issue in https://github.com/dotnet/wpf with a proposal and wait for a formal ack from the @dotnet/wpf-developers before investing too much time in this.
@roland5572 - Thank you for the good idea.
@willibrandon Thank you. I also found a possibility to increase the speed of WPF controls and save WPF system resources. I have updated the test results in this case.
If the users don't want to save the opened file history to the Windows system, the Windows API provides the OFN_DONTADDTORECENT flag to achieve this, but it is currently not available in WinForm class OpenFileDialog and SaveFileDialog.
Even if the reflection method OpenFileDialog.SetOption is called and OFN_DONTADDTORECENT is passed in, it also does not work.
Tested .NET Version:
.NET Framework 4.8 .NET 5.0