Closed ghost closed 2 years ago
I think this could be important for privacy and security reasons. Sometimes I want to open and save files without my Recent files list being updated. Perhaps I was working on some sensitive documents.
The WinForms file and folder dialogs currently do not support all of the options available to a file dialog. File dialog options such as don't add to recent, ok button needs interaction, force show hidden, and more, are currently not an option. In order to deliver a more improved file dialog experience, I propose we implement the relevant missing options and expose new public properties to allow the application to get and set the new file and folder dialog options.
namespace System.Windows.Forms
{
public partial class FileDialog
{
/// <summary>
/// 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; } = true;
/// <summary>
/// Gets or sets a value indicating whether the dialog box displays hidden and system files.
/// </summary>
[DefaultValue(false)]
public bool ShowHiddenFiles { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the items shown by default in the view's navigation pane are shown.
/// </summary>
[DefaultValue(true)]
public bool ShowPinnedPlaces { get; set; } = true;
/// <summary>
/// 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 OkRequiresInteraction { get; set; }
}
}
namespace System.Windows.Forms
{
public partial class OpenFileDialog
{
/// <summary>
/// Gets or sets a value indicating whether the dialog box shows a preview for selected files.
/// </summary>
[DefaultValue(false)]
public bool ShowPreview { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the dialog box allows to select read-only files.
/// </summary>
[DefaultValue(false)]
public bool SelectReadOnly { get; set; }
}
}
namespace System.Windows.Forms
{
public partial class SaveFileDialog
{
/// <summary>
/// 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; } = true;
/// <summary>
/// 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)]
public bool CheckWriteAccess { get; set; } = true;
}
}
namespace System.Windows.Forms
{
public partial class FolderBrowserDialog
{
/// <summary>
/// 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; } = true;
/// <summary>
/// Gets or sets a value indicating whether the dialog box displays hidden and system files.
/// </summary>
[DefaultValue(false)]
public bool ShowHiddenFiles { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the items shown by default in the view's navigation pane are hidden.
/// </summary>
[DefaultValue(true)]
public bool ShowPinnedPlaces { get; set; } = true;
/// <summary>
/// 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 OkRequiresInteraction { get; set; }
}
}
Since some of the proposed file dialog options might not be obvious, I recorded some videos to demonstrate them.
OkRequiresInteraction
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). Note: Disabling of the OK button does not prevent the dialog from being submitted by the Enter key.
https://user-images.githubusercontent.com/5017479/137844523-a2b15923-c496-4481-9941-6518909b46ea.mp4
ShowPinnedPlaces
Gets or sets a value indicating whether the items shown by default in the view's navigation pane are hidden.
https://user-images.githubusercontent.com/5017479/137844557-575f1bba-7e47-4db0-b0a5-dd7c6d61cea7.mp4
ShowHiddenFiles
Gets or sets a value indicating whether the dialog box displays hidden and system files.
https://user-images.githubusercontent.com/5017479/137844598-8fe5334d-7d29-4c25-acca-58f5d3bfbda4.mp4
AddToRecent
Gets or sets a value indicating whether the dialog box adds the folder being selected to the recent list.
https://user-images.githubusercontent.com/5017479/137843944-f00e8399-dd5b-41b8-8943-bfd0be76de10.mp4
ExpandedMode
Gets or sets a value indicating whether the dialog box is always opened in the expanded mode.
https://user-images.githubusercontent.com/5017479/137844642-7765180b-0a23-4248-b350-76a7c55c6626.mp4
CheckWriteAccess
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.
https://user-images.githubusercontent.com/5017479/137844713-1ab80c5b-1d1b-4de1-971d-705fe0074c8d.mp4
ShowPreview
Gets or sets a value indicating whether the dialog box shows a preview for selected files.
https://user-images.githubusercontent.com/5017479/137844744-c93c7007-9411-41cb-b01a-2b8acb9a62b3.mp4
IgnoreReadOnly
Gets or sets a value indicating whether the dialog box allows to select read-only files.
https://user-images.githubusercontent.com/5017479/137844790-4e40ba95-ef1f-459e-819f-a2900e99b452.mp4
Will this feature affect UI controls?
Yes.
Will VS Designer need to support the feature? If yes, describe how you expect it to funсtion.
The VS Designer will need to support the newly exposed properties at design time.
What impact will it have on accessibility?
None that I'm aware of.
Will this feature need to be localized or be localizable?
This will be handled by the description attribute for the new properties.
AddToRecent
for FileDialog
AddToRecent
for FolderBrowserDialog
.@willibrandon , thank you for taking time and propose the solution. This looks reasonable to me. I will get this triaged within team and get it ready for API review coming week.
This needs some additional research to check if its also needed on the (Vista) FolderBrowserDialog, since it doesn't share the same base class but shares much of the same behavior (due to also being a shell dialog since Vista).
If the FolderBrowserDialog by default also adds selected folders to the "recently used" list then it also should get this new API for consistency.
(If nobody beats me to it I can do the necessary experiments over the weekend, just wanted to mention it for now)
If I Windows-R "recent" and watch that folder I'm seeing the FolderBrowserDialog add the selected folders to Recent. Sometimes I have to refresh to see the recently selected folder(s).
It looks like FolderBrowserDialog could use some AddToRecent.
Also confirmed setting the FOS.DONTADDTORECENT option prevented the FolderBrowserDialog from adding to recent.
There could be things that I’m missing so I look forward to hearing your results.
@weltkante - I've done more testing and agree that the FolderBrowserDialog should also receive this new API.
I will work on updating the proposal and should have that ready at some point today. After you get a chance to experiment, if you would like me to add any relevant information, please let me know.
Thank you.
Sounds good, you seem to be confirming what I'm expecting. In the shell both file selection and folder selection go through the same APIs these days, so I'm expecting both to behave similarly and needing the same API, it was the same with a few other recent additions in .NET Core. Its a bit annoying that we can't go back and change the base class of FolderBrowserDialog to be more in line with what the Windows API looks like these days, so the next best option is simply to always consider any addition to file dialogs also to be added to the folder dialog. I'll double check over the weekend, but what you're reporting seems to confirm that the same is true here, so no need to wait for me if you want to update your API proposal.
If possible, can we please update the title of this issue to the following.
API Proposal: Implement AddToRecent for FileDialog and FolderBrowserDialog
I've updated the proposal to include the implementation of AddToRecent for the FolderBrowserDialog. Thank you @weltkante for pointing that out.
If there are any other concerns, please let me know so they can be addressed.
Thank you @willibrandon and @weltkante. During the review of this proposal, we looked at flags supported by native dialog enum and Winforms is missing a handful of them.
Use cases for some these flags are straight forward while other are little complicated. Did you get a chance to look at remaining flags and how they impact FileDialog
?
@dreddy-work - The thought had crossed my mind as a possible future proposal. Since this is my first one, I figured I would start small. I'll take a look now and familiarize myself with the flags and use cases.
@dreddy-work - The thought had crossed my mind as a possible future proposal. Since this is my first one, I figured I would start small. I'll take a look now and familiarize myself with the use cases.
Cool. We should extend the scope of this proposal and see what other flags we could/should add support for.
It'd be easier to take a more complete API proposal to the API Review Board. Once approved, we can implement the missing API either in one go or in a series of PRs.
It'd be easier to take a more complete API proposal to the API Review Board. Once approved, we can implement the missing API either in one go or in a series of PRs.
Thank you for the consideration. I'll start working on a more complete proposal which will include the remaining flags.
@dreddy-work - I agree that the use cases for the remaining flags are mostly straight forward and I should have no problems proposing the solutions for those however I might need a little guidance on imagining the use case for dialog box templates in WinForms. It seems like WinForms eliminates the need to support dialog box templates as it already supports the creation of custom dialog boxes by using the Windows Forms Designer. Unless there is something that the Dialog Editor and templates can do that the Designer and Windows Forms cannot, I'm not seeing good reason to support dialog box templates. I will take a closer look at the Dialog Editor and templates.
Perhaps the team has had a similar discussion about dialog box templates in the past and could bring me up to speed?
It seems like WinForms eliminates the need to support dialog box templates as it already supports the creation of custom dialog boxes by using the Windows Forms Designer.
Can you please clarify this point?
New properties will be surfaced in the property grid automatically. If those properties will contain something other than simple values (e.g. bool
, string
, etc.) then we'll need to discuss what'd be the best way to have those values set. But before we'll need to agree on the properties. Let's do this first, and then we can discuss any implications to the designer.
It seems like WinForms eliminates the need to support dialog box templates as it already supports the creation of custom dialog boxes by using the Windows Forms Designer.
Can you please clarify this point?
New properties will be surfaced in the property grid automatically. If those properties will contain something other than simple values (e.g.
bool
,string
, etc.) then we'll need to discuss what'd be the best way to have those values set. But before we'll need to agree on the properties. Let's do this first, and then we can discuss any implications to the designer.
I should have been more specific. What I was referring to are the flags ENABLETEMPLATE and ENABLETEMPLATEHANDLE which can be used to enable and specify dialog template resources. The dialog templates can be created using a Dialog Editor or can be created programmatically. My point was that I'm not sure if there is a need for the FileDialog
to support these 2 flags. Perhaps someone could provide some guidance on this topic. If I were to propose these 2 flags I would need help explaining the use cases.
The remaining flags appear to be more straightforward and I'm working on the proposal for those now.
Another flag which is unnecessary to implement is NONETWORKBUTTON. This flag corresponds to the old Windows 3.1 style Open dialog which has a button labeled Network that appears next to the drives combo box. Clicking the Network button lets you map a new network drive.
The NONETWORKBUTTON flag allows you to hide that button.
With that said, since the FileDialog
uses the Explorer-style dialog or the Vista-style dialog, there is no Network button to begin with, so there is no Network button to hide. This behavior and possible confusion with the new Explorer-style dialog is discussed here.
I should have been more specific. What I was referring to are the flags ENABLETEMPLATE and ENABLETEMPLATEHANDLE which can be used to enable and specify dialog template resources. The dialog templates can be created using a Dialog Editor or can be created programmatically. My point was that I'm not sure if there is a need for the
FileDialog
to support these 2 flags. Perhaps someone could provide some guidance on this topic. If I were to propose these 2 flags I would need help explaining the use cases.Only place in our code base i see using one of these flags is here and Handle passed was the Handle to the process file. I am still digging here to understand it better but i suggest continue with rest of the proposal for now.
Are we even talking about the right enum here? Isn't this the enum from the legacy (pre-Vista) dialog which is almost never going to be used anyways? I can't see these flags for the IFileDialog
interface (seems to be a different enum), nor can I see anything about dialog templates being supported. Am I missing something?
While you probably can call the legacy API and it will get redirected to IFileDialog when available (i.e. almost always, except on "Server Core" as reported here), I think many of those legacy settings no longer have a meaning. If you design new API you probably should target the actually used implementation and not the legacy API?
Are we even talking about the right enum here? Isn't this the enum from the legacy (pre-Vista) dialog which is almost never going to be used anyways? I can't see these flags for the
IFileDialog
interface (seems to be a different enum), nor can I see anything about dialog templates being supported. Am I missing something?
The IFileDialog options are here and dialog templates are not supported.
While you probably can call the legacy API and it will get redirected to IFileDialog when available (i.e. almost always, except on "Server Core" as reported here), I think many of those legacy settings no longer have a meaning. If you design new API you probably should target the actually used implementation and not the legacy API?
I agree and thank you for mentioning the Server Core exception. The IFileDialog flags haven't been explicitly mentioned yet but my plan was to propose those missing flags as well. Some of the missing legacy and Vista flags overlap, such as DONTADDTORECENT, so there is still some meaning there but I agree that we should start by focusing on the missing Vista flags, rather than the missing legacy flags.
The following Vista flags are missing:
FOS.STRICTFILETYPES FOS.PICKFOLDERS FOS.FORCEFILESYSTEM FOS.ALLNONSTORAGEITEMS FOS.SHAREAWARE FOS.NOREADONLYRETURN FOS.NOTESTFILECREATE FOS.HIDEMRUPLACES FOS.HIDEPINNEDPLACES FOS.OKBUTTONNEEDSINTERACTION FOS.DONTADDTORECENT FOS.FORCESHOWHIDDEN FOS.FORCEPREVIEWPANEON FOS.SUPPORTSTREAMABLEITEMS
we should start by focusing on the missing Vista flags, rather than the missing legacy flags
👍
The following Vista flags are missing:
FOS.STRICTFILETYPES FOS.PICKFOLDERS FOS.ALLNONSTORAGEITEMS FOS.SHAREAWARE FOS.NOREADONLYRETURN FOS.NOTESTFILECREATE FOS.HIDEMRUPLACES FOS.HIDEPINNEDPLACES FOS.OKBUTTONNEEDSINTERACTION FOS.DONTADDTORECENT FOS.FORCESHOWHIDDEN FOS.FORCEPREVIEWPANEON FOS.SUPPORTSTREAMABLEITEMS
Just to clarify, these are the flags that are not exposed to a user, and are up for consideration to be exposed. Do I understand this correctly?
Just to clarify, these are the flags that are not exposed to a user, and are up for consideration to be exposed. Do I understand this correctly?
Yes, those flags are currently not exposed. I'm not sure if it makes sense to expose all of them yet, I'm going through the use cases now and the classes that would require the behavior. So far I've looked at:
FOS.SHAREAWARE FOS.NOREADONLYRETURN FOS.NOTESTFILECREATE FOS.DONTADDTORECENT FOS.FORCESHOWHIDDEN
And for FileDialog
, those look reasonable to me. I also need to verify which of these make sense for the FolderBrowserDialog
.
Now working through the rest:
FOS.STRICTFILETYPES FOS.PICKFOLDERS FOS.FORCEFILESYSTEM FOS.ALLNONSTORAGEITEMS FOS.HIDEMRUPLACES FOS.HIDEPINNEDPLACES FOS.OKBUTTONNEEDSINTERACTION FOS.DEFAULTNOMINIMODE FOS.FORCEPREVIEWPANEON FOS.SUPPORTSTREAMABLEITEMS
Will report back here when finished.
This submission has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for 14 days.
It will be closed if no further activity occurs within 7 days of this comment.
I'm still looking at the remaining flags and their use cases and I must say that I don't feel as strongly about the rest of them as I do about FOS.DONTADDTORECENT, which makes them difficult to propose.
FOS.FORCESHOWHIDDEN and FOS.HIDEMRUPLACES I can see being useful and plan to propose those 2 flags as well but for the rest of the remaining flags, I have either found no use case or have found them to be more annoying than useful.
I'm working on summarizing my thoughts for each flag now and hope to finish that at some point today.
Thank you.
Yes, I think FOS.DONTADDTORECENT is more important. Other Flags can be implemented through additional programming code, but this flag can only be implemented through the underlying Windows API.
Yes, I think FOS.DONTADDTORECENT is more important.
I agree but we need to consider the other flags to make a more complete API proposal as mentioned earlier.
It'd be easier to take a more complete API proposal to the API Review Board. Once approved, we can implement the missing API either in one go or in a series of PRs.
Some of the flags and use cases have been new to me so its taken some time to get familiar with them all but I'm getting close. I'm working on a list now which will include each flag, it's definition, and some thoughts. From there we can decide which flags we could/should add support for, along with DONTADDTORECENT.
OkButtonNeedsInteraction
Controls whether the OK button needs interaction before it is enabled.
https://user-images.githubusercontent.com/5017479/136518334-deb03b94-adfe-42d4-9844-eec015262757.mp4
HidePinnedPlaces
Controls whether the items shown by default in the view's navigation pane are hidden.
https://user-images.githubusercontent.com/5017479/136639032-85d68bc2-bc0f-4649-9f19-9e314f9645fd.mp4
ExpandedMode, also known as DefaultNoMiniMode.
Controls whether to open the Save As dialog box in expanded mode.
https://user-images.githubusercontent.com/5017479/136643178-0443ea54-85f4-48be-a20e-27cd6733f5af.mp4
ForcePreviewPaneOn
Controls whether to always display the Open dialog box preview pane.
https://user-images.githubusercontent.com/5017479/136643896-8a15a60b-16b1-4666-87c0-219eb32b23c7.mp4
ForceShowHidden
Controls whether to include hidden and system items.
https://user-images.githubusercontent.com/5017479/136645209-19bb8d5d-b329-454d-a4db-3f469845ba75.mp4
AddToRecent
Controls whether to add the file being opened or saved, or the folder being selected, to the recent list.
https://user-images.githubusercontent.com/5017479/136714819-ce38632f-7730-48b6-aac1-90de9034f0ee.mp4
I'm unsure about AllNonStorageItems. I've experimented with shell namespace extensions and virtual files and folders but can't quite understand/see what this flag does when specified vs. not specified. If someone could help me think of the use case, or the lack thereof, I would greatly appreciate it.
FOS_ALLNONSTORAGEITEMS Enables the user to choose any item in the Shell namespace, not just those with SFGAO_STREAM or SFAGO_FILESYSTEM attributes. This flag cannot be combined with FOS_FORCEFILESYSTEM.
I don't believe there is a need to propose PickFolders since the FolderBrowserDialog
specifies this flag internally and already provides the behavior described.
FOS_PICKFOLDERS Present an Open dialog that offers a choice of folders rather than files.
HideMruPlaces either doesn't work or I do not understand the use case. The documentation mentions that the value is not supported as of Windows 7.
FOS_HIDEMRUPLACES Hide the list of places from which the user has recently opened or saved items. This value is not supported as of Windows 7.
This is a massive effort! Thank you heaps for the clips, very useful. My personal take is that the flags you recorded in the clips may be useful to some users. The last three - it is ok to skip. Are you still investigating further, or are you at the point of updating the API proposal?
Thank you for the feedback, I'm glad the clips help. Some of the behavior is subtle and trying to describe them with words can be difficult. I'm still investigating NoReadOnlyReturn, NoTestFileCreate, ShareAware, and StrictFileTypes.
I should have it wrapped up soon. Thank you for being patient, this has all been new to me and I want to do it justice.
I agree with @RussKie here. Thank you for keeping on top of it @willibrandon.
NoReadOnlyReturn
Controls whether read-only items are returned.
https://user-images.githubusercontent.com/5017479/136891252-367c4537-f1e8-4ed7-b66b-b8fe3097f788.mp4
NoTestFileCreate
Controls whether to create a test file.
https://user-images.githubusercontent.com/5017479/137071297-7030f608-daf0-43ac-a2ca-a5cbd752db5d.mp4
Note that NoTestFileCreate must be specified if the application saves the file on a create-nonmodify network share.
While investigating ShareAware I've realized there is an opportunity to provide applications the ability to perform custom actions during events such as a sharing violation, folder change, selection change, file type change, and overwriting a file. This could allow applications to handle these events and display their own dialogs to inform the user and/or perform a custom action, e.g., preventing navigation to a particular folder, presenting a custom overwrite prompt, responding to sharing violations, and showing/hiding certain dialog controls when the selected file type changes. Making these events available for applications to handle would seem to provide a tremendous amount of control when opening and saving files, and selecting folders. The events that could be added are FolderChange, FolderChanging, Overwrite, SelectionChange, ShareViolation, and TypeChange.
At the very least, the ShareViolation event should be included in the proposal in order for the ShareAware option to be properly implemented.
NoTestFileCreate
Controls whether to create a test file.
I'm a little confused by the behavior - with the flag=off a file was created (testfile1), and when the flag=on there was no file created (testfile2). The docs say that the created file may be inaccessible after the create. What was your experience?
I had a feeling NoTestFileCreate could be confusing. The behavior is subtle, but precise. Let me try to explain.
First, lets positively invert the name of the flag and call it TestFileCreate, which controls whether or not to create a test file. By default, when the SaveFileDialog
is closed, it first creates a test file to ensure that the file specified in the dialog can be opened and written to. It then quickly deletes the test file. That is precisely how it performs it’s write protection, full disk, network protection check. Just to be clear, this is the default behavior.
The tricky part of demonstrating this behavior is showing that the test file actually gets created, because the SaveFileDialog
deletes it so quickly. To do so, I created a create-nonmodify folder, which means files may be created, but once they are closed, they can no longer be modified or deleted. For my demo, with the flag=off, or NoTestFileCreate=false, which means TestFileCreate=true if we positively invert the meaning, a test file gets created, but the dialog is unable to delete it due to the folder's no-modify permissions. That is how I preserved the test file, preventing it from getting deleted, so that I could demonstrate that it got created in the first place.
Coincidentally, if an application saves a file on a create-nonmodify network share, it must specify NoTestFileCreate or else the SaveFileDialog
will violate the no-modify permission and receive a "You don't have permissions to modify files in this network location" when attempting to delete the test file, and will not return the specified file to be saved. Even worse, the test file gets left behind.
What this means is that applications that run on systems with create-nonmodify folders, they are unable to use the WinForms SaveFileDialog
because it currently does not support NoTestFileCreate. See a similar issue here as an example.
With the flag=on, or NoTestFileCreate=true, or TestFileCreate=false if we positively invert, a test file is not created. The file still gets returned, is accessible and can be saved, but special care should be taken by the user since the SaveFileDialog
did not perform it's write protection, full disk, network protection check.
Its a somewhat risky option, but specifying NoTestFileCreate is required in order to save a file on a create-nonmodify network share using the SaveFileDialog
. Small price to pay but that would be better than not having the option at all. If I were to guess, its designed for this exact purpose. A very specific bit.
Even the doc is subtly precise in it’s description of the flag.
Applications using this flag must perform file operations carefully, because a file cannot be reopened once it is closed.
Because a file cannot be reopened once it is closed? That sounds similar to a create-nonmodify network share but was not remotely obvious at first. Why couldn’t it have been more specific? That is why this process takes so long. Going from that sentence to figuring it needed to be a folder with those specific permissions to properly demonstrate the specific behavior was hard.
Almost everything about the file dialog options has a subtle characteristic. They are fascinating.
Thank you for the explanations 👍
I created a create-nonmodify folder, which means files may be created, but once they are closed, they can no longer be modified or deleted.
Ah, I must have missed "create" bit, and that's what got me confused.
I need to make the demo more clear somehow. Anyways, we should move on to ShareAware. That one is way more interesting.
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