Skip to content

Commit d87efca

Browse files
authored
API review for new properties in Storage.Pickers - SuggestedDefaultFolder, FileTypeChoices (#5771)
This is a design spec for adding new functionality to the Microsoft.Windows.Storage.Pickers APIs, including 2 main changes: - the SuggestedFolder and SuggestedStartFolder properties for all three picker types, - the new FileTypeChoices property for FileOpenPicker. Code implementation details can be found in (#5772)
1 parent 4774aae commit d87efca

File tree

4 files changed

+143
-10
lines changed

4 files changed

+143
-10
lines changed

specs/Storage.Pickers/FileOpenPicker.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,14 @@ runtimeclass FileOpenPicker
1919
FileOpenPicker(Microsoft.UI.WindowId windowId);
2020

2121
string CommitButtonText;
22+
23+
IMap<String, IVector<String>> FileTypeChoices{ get; };
2224
IVector<string> FileTypeFilter{ get; };
25+
26+
string SuggestedFolder;
27+
String SuggestedStartFolder;
2328
PickerLocationId SuggestedStartLocation;
29+
2430
PickerViewMode ViewMode;
2531

2632
Windows.Foundation.IAsyncOperation<PickFileResult> PickSingleFileAsync();
@@ -38,6 +44,18 @@ using Microsoft.Windows.Storage.Pickers;
3844

3945
var openPicker = new FileOpenPicker(this.AppWindow.Id)
4046
{
47+
// (Optional) Sets the folder that the file dialog always tries to display when it opens.
48+
// SuggestedFolder will not be overriden by the last picked folder.
49+
// If not specified, or the specified path doesn't exist, defaults to the last folder the user picked.
50+
// On first launch of the picker, SuggestedFolder takes precedence over the SuggestedStartFolder if both set.
51+
SuggestedFolder = @"C:\MyFiles",
52+
53+
// (Optional) Sets an initial folder path shown when the picker is first launched.
54+
// Once the user has picked from a directory, SuggestedStartFolder will be silently ignored.
55+
// Takes precedence over SuggestedStartLocation when both defined.
56+
// If this folder is not found, falls back to SuggestedStartLocation.
57+
SuggestedStartFolder = @"C:\MyFiles",
58+
4159
// (Optional) Specify the initial location for the picker.
4260
// If the specified location doesn't exist on the user's machine, it falls back to the DocumentsLibrary.
4361
// If not set, it defaults to PickerLocationId.Unspecified, and the system will use its default location.
@@ -47,6 +65,13 @@ var openPicker = new FileOpenPicker(this.AppWindow.Id)
4765
// If not specified, the system uses a default label of "Open" (suitably translated).
4866
CommitButtonText = "Choose selected files",
4967

68+
// (Optional) group file types into labeled choices
69+
// FileTypeChoices takes precedence over FileTypeFilter when both defined.
70+
FileTypeChoices = {
71+
{ "Documents", new List<string> { ".txt", ".doc", ".docx" } },
72+
{ "Pictures", new List<string> { ".png", ".jpg", ".jpeg", ".bmp" } }
73+
},
74+
5075
// (Optional) specify file extension filters. If not specified, defaults to all files (*.*).
5176
FileTypeFilter = { ".txt", ".pdf", ".doc", ".docx" },
5277

@@ -63,6 +88,18 @@ using namespace winrt::Microsoft::Windows::Storage::Pickers;
6388

6489
FileOpenPicker openPicker(AppWindow().Id());
6590

91+
// (Optional) Sets the folder that the file dialog always tries to display when it opens.
92+
// SuggestedFolder will not be overriden by the last picked folder.
93+
// If not specified, or the specified path doesn't exist, defaults to the last folder the user picked.
94+
// On first launch of the picker, SuggestedFolder takes precedence over the SuggestedStartFolder if both set.
95+
openPicker.SuggestedFolder(L"C:\\MyFiles");
96+
97+
// (Optional) Sets an initial folder path shown when the picker is first launched.
98+
// Once the user has picked from a directory, SuggestedStartFolder will be silently ignored.
99+
// Takes precedence over SuggestedStartLocation when both defined.
100+
// If this folder is not found, falls back to SuggestedStartLocation.
101+
openPicker.SuggestedStartFolder(L"C:\\MyFiles");
102+
66103
// (Optional) Specify the initial location for the picker.
67104
// If the specified location doesn't exist on the user's machine, it falls back to the DocumentsLibrary.
68105
// If not set, it defaults to PickerLocationId.Unspecified, and the system will use its default location.
@@ -72,6 +109,12 @@ openPicker.SuggestedStartLocation(PickerLocationId::DocumentsLibrary);
72109
// If not specified, the system uses a default label of "Open" (suitably translated).
73110
openPicker.CommitButtonText(L"Choose selected files");
74111

112+
// (Optional) group file types into labeled choices
113+
// FileTypeChoices takes precedence over FileTypeFilter when both defined.
114+
auto choices = openPicker.FileTypeChoices();
115+
choices.Insert(L"Documents", winrt::single_threaded_vector<winrt::hstring>({ L".txt", L".doc", L".docx" }));
116+
choices.Insert(L"Pictures", winrt::single_threaded_vector<winrt::hstring>({ L".png", L".jpg", L".jpeg", L".bmp" }));
117+
75118
// (Optional) specify file extension filters. If not specified, defaults to all files (*.*).
76119
openPicker.FileTypeFilter().ReplaceAll({ L".txt", L".pdf", L".doc", L".docx" });
77120

specs/Storage.Pickers/FileSavePicker.md

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,11 @@ runtimeclass FileSavePicker
1919
string CommitButtonText;
2020
string DefaultFileExtension;
2121
string SuggestedFileName;
22-
string SuggestedFolder;
2322

2423
IMap<string, IVector<string>> FileTypeChoices{ get; };
2524

25+
string SuggestedFolder;
26+
String SuggestedStartFolder;
2627
PickerLocationId SuggestedStartLocation;
2728

2829
Windows.Foundation.IAsyncOperation<PickFileResult> PickSaveFileAsync();
@@ -39,6 +40,18 @@ using Microsoft.Windows.Storage.Pickers;
3940

4041
var savePicker = new FileSavePicker(this.AppWindow.Id)
4142
{
43+
// (Optional) Sets the folder that the file save dialog always tries to display when it opens.
44+
// SuggestedFolder will not be overriden by the last picked folder.
45+
// If not specified, or the specified path doesn't exist, defaults to the last folder the user picked.
46+
// On first launch of the picker, SuggestedFolder takes precedence over the SuggestedStartFolder if both set.
47+
SuggestedFolder = @"C:\MyFiles",
48+
49+
// (Optional) Sets an initial folder path shown when the picker is first launched.
50+
// Once the user has picked from a directory, SuggestedStartFolder will be silently ignored.
51+
// Takes precedence over SuggestedStartLocation when both defined.
52+
// If this folder is not found, falls back to SuggestedStartLocation.
53+
SuggestedStartFolder = @"C:\MyFiles",
54+
4255
// (Optional) Specify the initial location for the picker.
4356
// If the specified location doesn't exist on the user's machine, it falls back to the DocumentsLibrary.
4457
// If not set, it defaults to PickerLocationId.Unspecified, and the system will use its default location.
@@ -47,10 +60,6 @@ var savePicker = new FileSavePicker(this.AppWindow.Id)
4760
// (Optional) specify the default file name. If not specified, use system default.
4861
SuggestedFileName = "My Document",
4962

50-
// (Optional) Sets the folder that the file save dialog displays when it opens.
51-
// If not specified or the specified path doesn't exist, defaults to the last folder the user visited.
52-
SuggestedFolder = @"C:\MyFiles",
53-
5463
// (Optional) specify the text displayed on the commit button.
5564
// If not specified, the system uses a default label of "Save" (suitably translated).
5665
CommitButtonText = "Save Document",
@@ -75,6 +84,18 @@ using namespace winrt::Microsoft::Windows::Storage::Pickers;
7584

7685
FileSavePicker savePicker(AppWindow().Id());
7786

87+
// (Optional) Sets the folder that the file save dialog always tries to display when it opens.
88+
// SuggestedFolder will not be overriden by the last picked folder.
89+
// If not specified, or the specified path doesn't exist, defaults to the last folder the user picked.
90+
// On first launch of the picker, SuggestedFolder takes precedence over the SuggestedStartFolder if both set.
91+
savePicker.SuggestedFolder(L"C:\\MyFiles");
92+
93+
// (Optional) Sets an initial folder path shown when the picker is first launched.
94+
// Once the user has picked from a directory, SuggestedStartFolder will be silently ignored.
95+
// Takes precedence over SuggestedStartLocation when both defined.
96+
// If this folder is not found, falls back to SuggestedStartLocation.
97+
savePicker.SuggestedStartFolder(L"C:\\MyFiles");
98+
7899
// (Optional) Specify the initial location for the picker.
79100
// If the specified location doesn't exist on the user's machine, it falls back to the DocumentsLibrary.
80101
// If not set, it defaults to PickerLocationId.Unspecified, and the system will use its default location.
@@ -83,10 +104,6 @@ savePicker.SuggestedStartLocation(PickerLocationId::DocumentsLibrary);
83104
// (Optional) specify the default file name. If not specified, use system default.
84105
savePicker.SuggestedFileName(L"NewDocument");
85106

86-
// (Optional) Sets the folder that the file save dialog displays when it opens.
87-
// If not specified or the specified path doesn't exist, defaults to the last folder the user visited.
88-
savePicker.SuggestedFolder = L"C:\\MyFiles",
89-
90107
// (Optional) specify the text displayed on the commit button.
91108
// If not specified, the system uses a default label of "Save" (suitably translated).
92109
savePicker.CommitButtonText(L"Save Document");

specs/Storage.Pickers/FolderPicker.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@ runtimeclass FolderPicker
2020

2121
string CommitButtonText;
2222

23+
string SuggestedFolder;
24+
String SuggestedStartFolder;
2325
PickerLocationId SuggestedStartLocation;
26+
2427
PickerViewMode ViewMode;
2528

2629
Windows.Foundation.IAsyncOperation<PickFolderResult> PickSingleFolderAsync();
@@ -42,6 +45,18 @@ using Microsoft.Windows.Storage.Pickers;
4245

4346
var folderPicker = new FolderPicker(this.AppWindow.Id)
4447
{
48+
// (Optional) Sets the folder that the folder dialog always tries to display when it opens.
49+
// SuggestedFolder will not be overriden by the last picked folder.
50+
// If not specified, or the specified path doesn't exist, defaults to the last folder the user picked.
51+
// On first launch of the picker, SuggestedFolder takes precedence over the SuggestedStartFolder if both set.
52+
SuggestedFolder = @"C:\MyFiles",
53+
54+
// (Optional) Sets an initial folder path shown when the picker is first launched.
55+
// Once the user has picked from a directory, SuggestedStartFolder will be silently ignored.
56+
// Takes precedence over SuggestedStartLocation when both defined.
57+
// If this folder is not found, falls back to SuggestedStartLocation.
58+
SuggestedStartFolder = @"C:\MyFiles",
59+
4560
// (Optional) Specify the initial location for the picker.
4661
// If the specified location doesn't exist on the user's machine, it falls back to the DocumentsLibrary.
4762
// If not set, it defaults to PickerLocationId.Unspecified, and the system will use its default location.
@@ -64,6 +79,18 @@ using namespace winrt::Microsoft::Windows::Storage::Pickers;
6479

6580
FolderPicker folderPicker(AppWindow().Id());
6681

82+
// (Optional) Sets the folder that the folder dialog always tries to display when it opens.
83+
// SuggestedFolder will not be overriden by the last picked folder.
84+
// If not specified, or the specified path doesn't exist, defaults to the last folder the user picked.
85+
// On first launch of the picker, SuggestedFolder takes precedence over the SuggestedStartFolder if both set.
86+
folderPicker.SuggestedFolder(L"C:\\MyFiles");
87+
88+
// (Optional) Sets an initial folder path shown when the picker is first launched.
89+
// Once the user has picked from a directory, SuggestedStartFolder will be silently ignored.
90+
// Takes precedence over SuggestedStartLocation when both defined.
91+
// If this folder is not found, falls back to SuggestedStartLocation.
92+
folderPicker.SuggestedStartFolder(L"C:\\MyFiles");
93+
6794
// (Optional) Specify the initial location for the picker.
6895
// If the specified location doesn't exist on the user's machine, it falls back to the DocumentsLibrary.
6996
// If not set, it defaults to PickerLocationId.Unspecified, and the system will use its default location.
@@ -124,3 +151,7 @@ else
124151
# See Also
125152

126153
[PickFolderResult](./PickFolderResult.md)
154+
155+
Notes:
156+
157+
- SuggestedStartFolder takes precedence over SuggestedStartLocation.

specs/Storage.Pickers/Microsoft.Windows.Storage.Pickers.md

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ in elevated scenarios.*
2828
1. *Similarly, the `FileSavePicker.SuggestedSaveFile` property (which returned a `StorageFile`)
2929
has been replaced. Its functionality is now covered by two string properties: `SuggestedFolder` and
3030
`SuggestedFileName`. These allow for suggesting the folder and file name for the save dialog.*
31+
1. Also adding the `SuggestedFolder` property to `FileOpenPicker` and `FolderPicker`, to better
32+
support a commonly requested scenario - setting a persistent folder for all pickers.
3133
1. *All new pickers are designed specifically for desktop apps and use a `WindowId` property to
3234
link the picker to its host window, replacing the `WinRT.Interop.InitializeWithWindow.Initialize`
3335
pattern.*
@@ -46,6 +48,15 @@ because the new APIs are currently designed for desktop scenarios where each use
4648
interactive session, and each session is completely independent of the other sessions on the device.
4749
This is in contrast to Xbox One or other multi-user devices.*
4850

51+
1. Adding `SuggestedStartFolder` for all 3 pickers. This allows setting the initial folder with
52+
an absolute folder path in string. When its specified folder exists, `SuggestedStartFolder`
53+
takes precedence over `SuggestedStartLocation`; when its folder not found, the picker falls back
54+
to `SuggestedStartLocation`, then to the system default.
55+
56+
1. Adding `FileTypeChoices` for `FileOpenPicker`. This allows the dialog of FileOpenPicker to have
57+
catagorized filter types. When both `FileTypeChoices` and `FileTypeFilter` are provided,
58+
`FileTypeChoices` is used and `FileTypeFilter` is ignored.
59+
4960
# Conceptual pages
5061

5162
# API
@@ -108,8 +119,14 @@ namespace Microsoft.Windows.Storage.Pickers
108119
FileOpenPicker(Microsoft.UI.WindowId windowId);
109120

110121
string CommitButtonText;
122+
123+
IMap<string, IVector<string>> FileTypeChoices{ get; };
111124
IVector<string> FileTypeFilter{ get; };
125+
126+
string SuggestedFolder;
127+
string SuggestedStartFolder;
112128
PickerLocationId SuggestedStartLocation;
129+
113130
PickerViewMode ViewMode;
114131

115132
Windows.Foundation.IAsyncOperation<PickFileResult> PickSingleFileAsync();
@@ -123,10 +140,11 @@ namespace Microsoft.Windows.Storage.Pickers
123140
string CommitButtonText;
124141
string DefaultFileExtension;
125142
string SuggestedFileName;
126-
string SuggestedFolder;
127143

128144
IMap<string, IVector<string>> FileTypeChoices{ get; };
129145

146+
string SuggestedFolder;
147+
string SuggestedStartFolder;
130148
PickerLocationId SuggestedStartLocation;
131149

132150
Windows.Foundation.IAsyncOperation<PickFileResult> PickSaveFileAsync();
@@ -138,10 +156,34 @@ namespace Microsoft.Windows.Storage.Pickers
138156

139157
string CommitButtonText;
140158

159+
string SuggestedFolder;
160+
string SuggestedStartFolder;
141161
PickerLocationId SuggestedStartLocation;
162+
142163
PickerViewMode ViewMode;
143164

144165
Windows.Foundation.IAsyncOperation<PickFolderResult> PickSingleFolderAsync();
145166
}
146167
}
147168
```
169+
170+
Note: **Understanding SuggestedStartFolder/SuggestedStartLocation vs SuggestedFolder:**
171+
172+
These two kinds of properties have fundamentally different behaviors in terms of when and how they
173+
affect the picker:
174+
175+
- `SuggestedFolder` sets the path that will always be tried when opening the picker, regardless of
176+
the user's previous operations. This uses the [SetFolder](https://learn.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-ifiledialog-setfolder)
177+
method of the underlying COM APIs and takes precedence over any user navigation history.
178+
179+
- `SuggestedStartFolder` sets the path shown only the first time the user launches the picker
180+
(typically when the app is newly installed). After the user has picked a file, subsequent
181+
launches of the picker will open to the user's last selected folder, and `SuggestedStartFolder`
182+
becomes silent. This corresponds to the [SetDefaultFolder](https://learn.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-ifiledialog-setdefaultfolder)
183+
method in the COM API.
184+
185+
The effective time span of `SuggestedStartFolder` is the same as that of `SuggestedStartLocation`,
186+
both only influence the picker's initial behavior before user interaction establishes a
187+
navigation history.
188+
189+
`SuggestedStartFolder` takes precedence over `SuggestedStartLocation` when both specified.

0 commit comments

Comments
 (0)