diff --git a/Samples/StoragePickers/README.md b/Samples/StoragePickers/README.md
new file mode 100644
index 000000000..d71eee3f2
--- /dev/null
+++ b/Samples/StoragePickers/README.md
@@ -0,0 +1,94 @@
+## The Storage Pickers Samples
+
+- Demonstrates the `Microsoft.Windows.Storage.Pickers` APIs inside a Windows App SDK app.
+- Targets Windows App SDK **1.8 or later**.
+- Three tabs showcase `FileOpenPicker`, `FileSavePicker`, and `FolderPicker` usage end to end.
+
+## 📸 Screenshot of App Layout
+
+
+
+## Deploy the Sample Packaged App Locally
+
+1. Open `cpp-sample/FilePickersAppSinglePackaged.sln` or `cs-sample/FilePickersAppSinglePackaged.sln` in Visual Studio, right click on the project, select "Package and Publish" > "Create App Package"
+
+
+
+2. Select Sideloading > Next
+
+
+
+3. Create and Trust your own test certification
+
+
+
+
+
+4. Create package
+
+
+
+5. Open the built result
+
+
+
+5. Run Install.ps1 in powershell
+
+
+
+*Note:*
+
+If encountering error like below:
+
+> Add-AppxPackage: Cannot find path 'C:\FilePickersAppSinglePackaged_1.0.1.0_x64_Debug_Test\Dependencies\x86\Microsoft.VCLibs.x86.Debug.14.00.appx C:\FilePickersAppSinglePackaged_1.0.1.0_x64_Debug_Test\Dependencies\x86\Microsoft.VCLibs.x86.Debug.14.00.Desktop.appx C:\FilePickersAppSinglePackaged_1.0.1.0_x64_Debug_Test\Dependencies\x64\Microsoft.VCLibs.x64.Debug.14.00.appx C:\FilePickersAppSinglePackaged_1.0.1.0_x64_Debug_Test\Dependencies\x64\Microsoft.VCLibs.x64.Debug.14.00.Desktop.appx' because it does not exist.
+
+Replace lines 483-491 in `Add-AppDevPackage.ps1` with below script and try again:
+
+```ps
+if ($DependencyPackages.FullName.Count -gt 0)
+{
+ Write-Host $UiStrings.DependenciesFound
+ $DependencyPackages.FullName
+
+
+ # Install dependencies one by one first
+ foreach ($dep in $DependencyPackages.FullName) {
+ echo "Installing dependency: $dep"
+ try {
+ Add-AppxPackage -Path $dep -ForceApplicationShutdown
+ echo "Successfully installed: $dep"
+ } catch {
+ echo "Failed to install dependency: $dep - $($_.Exception.Message)"
+ }
+ }
+
+ # Now install the main package
+ echo "Installing main package: $($DeveloperPackagePath.FullName)"
+ Add-AppxPackage -Path $DeveloperPackagePath.FullName -ForceApplicationShutdown
+}
+```
+
+Screenshot of this error:
+
+
+Screenshot of this mitigation:
+
+
+
+With the dependency *.appx files correctly installed, the project should be debugged in Visual Studio smoothly.
+
+
+
+
+## 🚀 Run
+
+1. Open `cpp-sample/FilePickersAppSinglePackaged.sln` or `cs-sample/FilePickersAppSinglePackaged.sln` in Visual Studio.
+1. Restore NuGet packages and ensure the Windows App SDK 1.8 runtime is installed locally.
+1. Build and run.
+
+
+## More to explore
+
+- [Microsoft.Windows.Storage.Pickers Namespace](https://learn.microsoft.com/en-us/windows/windows-app-sdk/api/winrt/microsoft.windows.storage.pickers)
+- [Design Specs of Microsoft.Windows.Storage.Pickers](https://github.com/microsoft/WindowsAppSDK/blob/release/1.8-stable/specs/Storage.Pickers/Microsoft.Windows.Storage.Pickers.md)
+- [Windows App SDK](https://github.com/microsoft/WindowsAppSDK/)
diff --git a/Samples/StoragePickers/cpp-sample/App.xaml b/Samples/StoragePickers/cpp-sample/App.xaml
new file mode 100644
index 000000000..5a11fec41
--- /dev/null
+++ b/Samples/StoragePickers/cpp-sample/App.xaml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/StoragePickers/cpp-sample/App.xaml.cpp b/Samples/StoragePickers/cpp-sample/App.xaml.cpp
new file mode 100644
index 000000000..673e30140
--- /dev/null
+++ b/Samples/StoragePickers/cpp-sample/App.xaml.cpp
@@ -0,0 +1,43 @@
+#include "pch.h"
+#include "App.xaml.h"
+#include "MainWindow.xaml.h"
+
+using namespace winrt;
+using namespace Microsoft::UI::Xaml;
+
+// To learn more about WinUI, the WinUI project structure,
+// and more about our project templates, see: http://aka.ms/winui-project-info.
+
+namespace winrt::FilePickersAppSinglePackaged::implementation
+{
+ ///
+ /// Initializes the singleton application object. This is the first line of authored code
+ /// executed, and as such is the logical equivalent of main() or WinMain().
+ ///
+ App::App()
+ {
+ // Xaml objects should not call InitializeComponent during construction.
+ // See https://github.com/microsoft/cppwinrt/tree/master/nuget#initializecomponent
+
+#if defined _DEBUG && !defined DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION
+ UnhandledException([](IInspectable const&, UnhandledExceptionEventArgs const& e)
+ {
+ if (IsDebuggerPresent())
+ {
+ auto errorMessage = e.Message();
+ __debugbreak();
+ }
+ });
+#endif
+ }
+
+ ///
+ /// Invoked when the application is launched.
+ ///
+ /// Details about the launch request and process.
+ void App::OnLaunched([[maybe_unused]] LaunchActivatedEventArgs const& e)
+ {
+ window = make();
+ window.Activate();
+ }
+}
diff --git a/Samples/StoragePickers/cpp-sample/App.xaml.h b/Samples/StoragePickers/cpp-sample/App.xaml.h
new file mode 100644
index 000000000..bf0d7c789
--- /dev/null
+++ b/Samples/StoragePickers/cpp-sample/App.xaml.h
@@ -0,0 +1,16 @@
+#pragma once
+
+#include "App.xaml.g.h"
+
+namespace winrt::FilePickersAppSinglePackaged::implementation
+{
+ struct App : AppT
+ {
+ App();
+
+ void OnLaunched(Microsoft::UI::Xaml::LaunchActivatedEventArgs const&);
+
+ private:
+ winrt::Microsoft::UI::Xaml::Window window{ nullptr };
+ };
+}
diff --git a/Samples/StoragePickers/cpp-sample/Assets/LockScreenLogo.scale-200.png b/Samples/StoragePickers/cpp-sample/Assets/LockScreenLogo.scale-200.png
new file mode 100644
index 000000000..7440f0d4b
Binary files /dev/null and b/Samples/StoragePickers/cpp-sample/Assets/LockScreenLogo.scale-200.png differ
diff --git a/Samples/StoragePickers/cpp-sample/Assets/SplashScreen.scale-200.png b/Samples/StoragePickers/cpp-sample/Assets/SplashScreen.scale-200.png
new file mode 100644
index 000000000..32f486a86
Binary files /dev/null and b/Samples/StoragePickers/cpp-sample/Assets/SplashScreen.scale-200.png differ
diff --git a/Samples/StoragePickers/cpp-sample/Assets/Square150x150Logo.scale-200.png b/Samples/StoragePickers/cpp-sample/Assets/Square150x150Logo.scale-200.png
new file mode 100644
index 000000000..53ee3777e
Binary files /dev/null and b/Samples/StoragePickers/cpp-sample/Assets/Square150x150Logo.scale-200.png differ
diff --git a/Samples/StoragePickers/cpp-sample/Assets/Square44x44Logo.scale-200.png b/Samples/StoragePickers/cpp-sample/Assets/Square44x44Logo.scale-200.png
new file mode 100644
index 000000000..f713bba67
Binary files /dev/null and b/Samples/StoragePickers/cpp-sample/Assets/Square44x44Logo.scale-200.png differ
diff --git a/Samples/StoragePickers/cpp-sample/Assets/Square44x44Logo.targetsize-24_altform-unplated.png b/Samples/StoragePickers/cpp-sample/Assets/Square44x44Logo.targetsize-24_altform-unplated.png
new file mode 100644
index 000000000..dc9f5bea0
Binary files /dev/null and b/Samples/StoragePickers/cpp-sample/Assets/Square44x44Logo.targetsize-24_altform-unplated.png differ
diff --git a/Samples/StoragePickers/cpp-sample/Assets/StoreLogo.png b/Samples/StoragePickers/cpp-sample/Assets/StoreLogo.png
new file mode 100644
index 000000000..a4586f26b
Binary files /dev/null and b/Samples/StoragePickers/cpp-sample/Assets/StoreLogo.png differ
diff --git a/Samples/StoragePickers/cpp-sample/Assets/Wide310x150Logo.scale-200.png b/Samples/StoragePickers/cpp-sample/Assets/Wide310x150Logo.scale-200.png
new file mode 100644
index 000000000..8b4a5d0dd
Binary files /dev/null and b/Samples/StoragePickers/cpp-sample/Assets/Wide310x150Logo.scale-200.png differ
diff --git a/Samples/StoragePickers/cpp-sample/FilePickersAppSinglePackaged.sln b/Samples/StoragePickers/cpp-sample/FilePickersAppSinglePackaged.sln
new file mode 100644
index 000000000..cb1b06ddf
--- /dev/null
+++ b/Samples/StoragePickers/cpp-sample/FilePickersAppSinglePackaged.sln
@@ -0,0 +1,40 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.12.35707.178 d17.12
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FilePickersAppSinglePackaged", "FilePickersAppSinglePackaged.vcxproj", "{FC188327-1E71-4DC4-9B57-EB2A2CACEE12}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|ARM64 = Debug|ARM64
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|ARM64 = Release|ARM64
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {FC188327-1E71-4DC4-9B57-EB2A2CACEE12}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {FC188327-1E71-4DC4-9B57-EB2A2CACEE12}.Debug|ARM64.Build.0 = Debug|ARM64
+ {FC188327-1E71-4DC4-9B57-EB2A2CACEE12}.Debug|ARM64.Deploy.0 = Debug|ARM64
+ {FC188327-1E71-4DC4-9B57-EB2A2CACEE12}.Debug|x64.ActiveCfg = Debug|x64
+ {FC188327-1E71-4DC4-9B57-EB2A2CACEE12}.Debug|x64.Build.0 = Debug|x64
+ {FC188327-1E71-4DC4-9B57-EB2A2CACEE12}.Debug|x64.Deploy.0 = Debug|x64
+ {FC188327-1E71-4DC4-9B57-EB2A2CACEE12}.Debug|x86.ActiveCfg = Debug|Win32
+ {FC188327-1E71-4DC4-9B57-EB2A2CACEE12}.Debug|x86.Build.0 = Debug|Win32
+ {FC188327-1E71-4DC4-9B57-EB2A2CACEE12}.Debug|x86.Deploy.0 = Debug|Win32
+ {FC188327-1E71-4DC4-9B57-EB2A2CACEE12}.Release|ARM64.ActiveCfg = Release|ARM64
+ {FC188327-1E71-4DC4-9B57-EB2A2CACEE12}.Release|ARM64.Build.0 = Release|ARM64
+ {FC188327-1E71-4DC4-9B57-EB2A2CACEE12}.Release|ARM64.Deploy.0 = Release|ARM64
+ {FC188327-1E71-4DC4-9B57-EB2A2CACEE12}.Release|x64.ActiveCfg = Release|x64
+ {FC188327-1E71-4DC4-9B57-EB2A2CACEE12}.Release|x64.Build.0 = Release|x64
+ {FC188327-1E71-4DC4-9B57-EB2A2CACEE12}.Release|x64.Deploy.0 = Release|x64
+ {FC188327-1E71-4DC4-9B57-EB2A2CACEE12}.Release|x86.ActiveCfg = Release|Win32
+ {FC188327-1E71-4DC4-9B57-EB2A2CACEE12}.Release|x86.Build.0 = Release|Win32
+ {FC188327-1E71-4DC4-9B57-EB2A2CACEE12}.Release|x86.Deploy.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Samples/StoragePickers/cpp-sample/FilePickersAppSinglePackaged.vcxproj b/Samples/StoragePickers/cpp-sample/FilePickersAppSinglePackaged.vcxproj
new file mode 100644
index 000000000..ba8b94708
--- /dev/null
+++ b/Samples/StoragePickers/cpp-sample/FilePickersAppSinglePackaged.vcxproj
@@ -0,0 +1,240 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ true
+ true
+ {fc188327-1e71-4dc4-9b57-eb2a2cacee12}
+ FilePickersAppSinglePackaged
+ FilePickersAppSinglePackaged
+
+ $(RootNamespace)
+ en-US
+ 16.0
+ false
+ true
+ Windows Store
+ 10.0
+ 10.0
+ 10.0.17763.0
+ true
+ true
+ true
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Debug
+ ARM64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+ Release
+ ARM64
+
+
+
+ Application
+ v143
+ Unicode
+ true
+
+
+ true
+ true
+
+
+ false
+ true
+ false
+
+
+
+
+
+
+
+
+
+
+ Use
+ pch.h
+ $(IntDir)pch.pch
+ Level4
+ %(AdditionalOptions) /bigobj
+
+
+
+
+ _DEBUG;%(PreprocessorDefinitions)
+
+
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+
+
+ true
+ true
+
+
+
+
+ Designer
+
+
+
+
+
+
+
+
+ App.xaml
+
+
+ MainWindow.xaml
+
+
+
+
+
+
+
+
+ Create
+
+
+ App.xaml
+
+
+ MainWindow.xaml
+
+
+
+
+
+ Code
+ MainWindow.xaml
+
+
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/StoragePickers/cpp-sample/FilePickersAppSinglePackaged.vcxproj.filters b/Samples/StoragePickers/cpp-sample/FilePickersAppSinglePackaged.vcxproj.filters
new file mode 100644
index 000000000..d10d1473d
--- /dev/null
+++ b/Samples/StoragePickers/cpp-sample/FilePickersAppSinglePackaged.vcxproj.filters
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+
+
+ {fc188327-1e71-4dc4-9b57-eb2a2cacee12}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/StoragePickers/cpp-sample/MainWindow.idl b/Samples/StoragePickers/cpp-sample/MainWindow.idl
new file mode 100644
index 000000000..2c7202940
--- /dev/null
+++ b/Samples/StoragePickers/cpp-sample/MainWindow.idl
@@ -0,0 +1,8 @@
+namespace FilePickersAppSinglePackaged
+{
+ [default_interface]
+ runtimeclass MainWindow : Microsoft.UI.Xaml.Window
+ {
+ MainWindow();
+ }
+}
diff --git a/Samples/StoragePickers/cpp-sample/MainWindow.xaml b/Samples/StoragePickers/cpp-sample/MainWindow.xaml
new file mode 100644
index 000000000..0bce46907
--- /dev/null
+++ b/Samples/StoragePickers/cpp-sample/MainWindow.xaml
@@ -0,0 +1,180 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/StoragePickers/cpp-sample/MainWindow.xaml.cpp b/Samples/StoragePickers/cpp-sample/MainWindow.xaml.cpp
new file mode 100644
index 000000000..2ca82bc4c
--- /dev/null
+++ b/Samples/StoragePickers/cpp-sample/MainWindow.xaml.cpp
@@ -0,0 +1,412 @@
+#include "pch.h"
+#include "MainWindow.xaml.h"
+#if __has_include("MainWindow.g.cpp")
+#include "MainWindow.g.cpp"
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+using namespace winrt;
+using namespace Microsoft::UI::Xaml;
+using namespace Microsoft::UI::Windowing;
+using namespace Microsoft::Windows::Storage::Pickers;
+using namespace Windows::Data::Json;
+
+namespace
+{
+ std::wstring TrimString(std::wstring_view text)
+ {
+ auto start = text.find_first_not_of(L" \t\r\n'\"");
+ if (start == std::wstring_view::npos)
+ {
+ return {};
+ }
+
+ auto end = text.find_last_not_of(L" \t\r\n'\"");
+ return std::wstring{ text.substr(start, end - start + 1) };
+ }
+
+ bool IsChecked(Microsoft::UI::Xaml::Controls::CheckBox const& checkbox)
+ {
+ if (auto value = checkbox.IsChecked())
+ {
+ return value.Value();
+ }
+
+ return false;
+ }
+
+ std::wstring FileNameFromPath(std::wstring_view path)
+ {
+ if (path.empty())
+ {
+ return {};
+ }
+
+ std::filesystem::path fsPath{ path };
+ return fsPath.filename().wstring();
+ }
+}
+
+namespace winrt::FilePickersAppSinglePackaged::implementation
+{
+ MainWindow::MainWindow()
+ {
+ InitializeComponent();
+ Title(L"File Pickers Sample App");
+
+ if (auto appWindow = this->AppWindow())
+ {
+ appWindow.Resize({ 1800, 1100 });
+ }
+ }
+
+ void MainWindow::LogResult(winrt::hstring const& message)
+ {
+ using namespace std::chrono;
+
+ auto now = system_clock::now();
+ auto rawTime = system_clock::to_time_t(now);
+ tm localTime{};
+ localtime_s(&localTime, &rawTime);
+
+ std::wstringstream timestampStream;
+ timestampStream << std::put_time(&localTime, L"%H:%M:%S");
+
+ std::wstring existing{ ResultsTextBlock().Text().c_str() };
+
+ std::wstring newEntry;
+ newEntry.reserve(existing.size() + message.size() + 16);
+ newEntry.append(L"[");
+ newEntry.append(timestampStream.str());
+ newEntry.append(L"] ");
+ newEntry.append(message.c_str());
+ newEntry.append(L"\n");
+ newEntry.append(existing);
+
+ ResultsTextBlock().Text(winrt::hstring{ newEntry });
+ }
+
+ PickerLocationId MainWindow::GetSelectedNewLocationId()
+ {
+ switch (StartLocationComboBox().SelectedIndex())
+ {
+ case 0: return PickerLocationId::DocumentsLibrary;
+ case 1: return PickerLocationId::ComputerFolder;
+ case 2: return PickerLocationId::Desktop;
+ case 3: return PickerLocationId::Downloads;
+
+ // HomeGroup is excluded from the new PickerLocationId enum. This example demonstrates how the error would look like.
+ case 4: return static_cast(4);
+
+ case 5: return PickerLocationId::MusicLibrary;
+ case 6: return PickerLocationId::PicturesLibrary;
+ case 7: return PickerLocationId::VideosLibrary;
+ case 8: return PickerLocationId::Objects3D;
+ case 9: return PickerLocationId::Unspecified;
+ case 10: return static_cast(10);
+ default: throw hresult_invalid_argument(L"Invalid location selected");
+ }
+ }
+
+ PickerViewMode MainWindow::GetSelectedNewViewMode()
+ {
+ switch (ViewModeComboBox().SelectedIndex())
+ {
+ case 0: return PickerViewMode::List;
+ case 1: return PickerViewMode::Thumbnail;
+ case 2: return static_cast(2);
+ default: throw hresult_invalid_argument(L"Invalid view mode selected");
+ }
+ }
+
+ std::vector MainWindow::GetFileFilters()
+ {
+ std::wstring text{ FileTypeFilterInput().Text().c_str() };
+
+ std::vector filters;
+
+ std::wstringstream stream{ text };
+ std::wstring item;
+ while (std::getline(stream, item, L','))
+ {
+ auto trimmed = TrimString(item);
+ if (!trimmed.empty())
+ {
+ filters.emplace_back(trimmed);
+ }
+ }
+
+ if (filters.empty())
+ {
+ filters.emplace_back(L"*");
+ }
+
+ return filters;
+ }
+
+ winrt::fire_and_forget MainWindow::NewPickSingleFile_Click(winrt::Windows::Foundation::IInspectable const&, RoutedEventArgs const&)
+ {
+ auto lifetime = get_strong();
+
+ try
+ {
+ FileOpenPicker picker{ this->AppWindow().Id() };
+
+ if (IsChecked(CommitButtonCheckBox()))
+ {
+ picker.CommitButtonText(CommitButtonTextInput().Text());
+ }
+
+ if (IsChecked(ViewModeCheckBox()))
+ {
+ picker.ViewMode(GetSelectedNewViewMode());
+ }
+
+ if (IsChecked(SuggestedStartLocationCheckBox()))
+ {
+ picker.SuggestedStartLocation(GetSelectedNewLocationId());
+ }
+
+ if (IsChecked(FileTypeFilterCheckBox()))
+ {
+ for (auto const& filter : GetFileFilters())
+ {
+ picker.FileTypeFilter().Append(filter);
+ }
+ }
+
+ auto result = co_await picker.PickSingleFileAsync();
+ if (result)
+ {
+ std::wstring path{ result.Path().c_str() };
+ std::wstring fileName = FileNameFromPath(path);
+
+ std::wstringstream message;
+ message << L"New FileOpenPicker - PickSingleFileAsync:\nFile: " << fileName << L"\nPath: " << path;
+ LogResult(winrt::hstring{ message.str() });
+ }
+ else
+ {
+ LogResult(L"New FileOpenPicker - PickSingleFileAsync: Operation cancelled");
+ }
+ }
+ catch (winrt::hresult_error const& ex)
+ {
+ std::wstring message = L"Error in New FileOpenPicker: ";
+ message.append(ex.message().c_str());
+ LogResult(winrt::hstring{ message });
+ }
+
+ co_return;
+ }
+
+ winrt::fire_and_forget MainWindow::NewPickMultipleFiles_Click(winrt::Windows::Foundation::IInspectable const&, RoutedEventArgs const&)
+ {
+ auto lifetime = get_strong();
+
+ try
+ {
+ FileOpenPicker picker{ this->AppWindow().Id() };
+
+ if (IsChecked(CommitButtonCheckBox()))
+ {
+ picker.CommitButtonText(CommitButtonTextInput().Text());
+ }
+
+ if (IsChecked(ViewModeCheckBox()))
+ {
+ picker.ViewMode(GetSelectedNewViewMode());
+ }
+
+ if (IsChecked(SuggestedStartLocationCheckBox()))
+ {
+ picker.SuggestedStartLocation(GetSelectedNewLocationId());
+ }
+
+ if (IsChecked(FileTypeFilterCheckBox()))
+ {
+ for (auto const& filter : GetFileFilters())
+ {
+ picker.FileTypeFilter().Append(filter);
+ }
+ }
+
+ auto results = co_await picker.PickMultipleFilesAsync();
+ if (results && results.Size() > 0)
+ {
+ std::wstringstream message;
+ message << L"New FileOpenPicker - PickMultipleFilesAsync: " << results.Size() << L" files\n";
+
+ for (auto const& item : results)
+ {
+ std::wstring path{ item.Path().c_str() };
+ message << L"- " << FileNameFromPath(path) << L": " << path << L"\n";
+ }
+
+ LogResult(winrt::hstring{ message.str() });
+ }
+ else
+ {
+ LogResult(L"New FileOpenPicker - PickMultipleFilesAsync: Operation cancelled or no files selected");
+ }
+ }
+ catch (winrt::hresult_error const& ex)
+ {
+ std::wstring message = L"Error in New PickMultipleFilesAsync: ";
+ message.append(ex.message().c_str());
+ LogResult(winrt::hstring{ message });
+ }
+
+ co_return;
+ }
+
+ winrt::fire_and_forget MainWindow::NewPickSaveFile_Click(winrt::Windows::Foundation::IInspectable const&, RoutedEventArgs const&)
+ {
+ auto lifetime = get_strong();
+
+ try
+ {
+ FileSavePicker picker{ this->AppWindow().Id() };
+
+ if (IsChecked(SuggestedFileNameCheckBox()))
+ {
+ picker.SuggestedFileName(SuggestedFileNameInput().Text());
+ }
+
+ if (IsChecked(DefaultFileExtensionCheckBox()))
+ {
+ picker.DefaultFileExtension(DefaultFileExtensionInput().Text());
+ }
+
+ if (IsChecked(SuggestedFolderCheckBox()))
+ {
+ auto folder = TrimString(SuggestedFolderInput().Text().c_str());
+ if (!folder.empty())
+ {
+ picker.SuggestedFolder(winrt::hstring{ folder });
+ }
+ }
+
+ if (IsChecked(FileTypeChoicesCheckBox()))
+ {
+ auto jsonText = TrimString(FileTypeChoicesInput().Text().c_str());
+ if (!jsonText.empty())
+ {
+ JsonObject jsonObject;
+ if (JsonObject::TryParse(jsonText, jsonObject))
+ {
+ for (auto const& kvp : jsonObject)
+ {
+ std::vector values;
+ if (kvp.Value().ValueType() == JsonValueType::Array)
+ {
+ for (auto const& value : kvp.Value().GetArray())
+ {
+ if (value.ValueType() == JsonValueType::String)
+ {
+ values.emplace_back(value.GetString());
+ }
+ }
+ }
+
+ if (!values.empty())
+ {
+ picker.FileTypeChoices().Insert(kvp.Key(), winrt::single_threaded_vector(std::move(values)));
+ }
+ }
+ }
+ else
+ {
+ LogResult(L"Error in New FileSavePicker: Unable to parse FileTypeChoices JSON");
+ }
+ }
+ }
+
+ if (IsChecked(CommitButtonCheckBox()))
+ {
+ picker.CommitButtonText(CommitButtonTextInput().Text());
+ }
+
+ if (IsChecked(SuggestedStartLocationCheckBox()))
+ {
+ picker.SuggestedStartLocation(GetSelectedNewLocationId());
+ }
+
+ auto result = co_await picker.PickSaveFileAsync();
+ if (result)
+ {
+ std::wstring path{ result.Path().c_str() };
+ std::wstring fileName = FileNameFromPath(path);
+
+ std::wstringstream message;
+ message << L"New FileSavePicker picked file: \n" << fileName << L"\nPath: " << path;
+ LogResult(winrt::hstring{ message.str() });
+ }
+ else
+ {
+ LogResult(L"New FileSavePicker with FileTypeChoices\nOperation cancelled");
+ }
+ }
+ catch (winrt::hresult_error const& ex)
+ {
+ std::wstring message = L"Error in New FileTypeChoices: ";
+ message.append(ex.message().c_str());
+ LogResult(winrt::hstring{ message });
+ }
+
+ co_return;
+ }
+
+ winrt::fire_and_forget MainWindow::NewPickFolder_Click(winrt::Windows::Foundation::IInspectable const&, RoutedEventArgs const&)
+ {
+ auto lifetime = get_strong();
+
+ try
+ {
+ FolderPicker picker{ this->AppWindow().Id() };
+
+ if (IsChecked(CommitButtonCheckBox()))
+ {
+ picker.CommitButtonText(CommitButtonTextInput().Text());
+ }
+
+ if (IsChecked(SuggestedStartLocationCheckBox()))
+ {
+ picker.SuggestedStartLocation(GetSelectedNewLocationId());
+ }
+
+ auto result = co_await picker.PickSingleFolderAsync();
+ if (result)
+ {
+ std::wstring path{ result.Path().c_str() };
+ std::wstring folderName = FileNameFromPath(path);
+
+ std::wstringstream message;
+ message << L"New FolderPicker - PickSingleFolderAsync:\nFolder: " << folderName << L"\nPath: " << path;
+ LogResult(winrt::hstring{ message.str() });
+ }
+ else
+ {
+ LogResult(L"New FolderPicker - PickSingleFolderAsync: Operation cancelled");
+ }
+ }
+ catch (winrt::hresult_error const& ex)
+ {
+ std::wstring message = L"Error in New FolderPicker: ";
+ message.append(ex.message().c_str());
+ LogResult(winrt::hstring{ message });
+ }
+
+ co_return;
+ }
+}
diff --git a/Samples/StoragePickers/cpp-sample/MainWindow.xaml.h b/Samples/StoragePickers/cpp-sample/MainWindow.xaml.h
new file mode 100644
index 000000000..11ea6c41c
--- /dev/null
+++ b/Samples/StoragePickers/cpp-sample/MainWindow.xaml.h
@@ -0,0 +1,31 @@
+#pragma once
+
+#include "MainWindow.g.h"
+
+#include
+
+namespace winrt::FilePickersAppSinglePackaged::implementation
+{
+ struct MainWindow : MainWindowT
+ {
+ MainWindow();
+
+ winrt::fire_and_forget NewPickSingleFile_Click(winrt::Windows::Foundation::IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& args);
+ winrt::fire_and_forget NewPickMultipleFiles_Click(winrt::Windows::Foundation::IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& args);
+ winrt::fire_and_forget NewPickSaveFile_Click(winrt::Windows::Foundation::IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& args);
+ winrt::fire_and_forget NewPickFolder_Click(winrt::Windows::Foundation::IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& args);
+
+ private:
+ void LogResult(winrt::hstring const& message);
+ Microsoft::Windows::Storage::Pickers::PickerLocationId GetSelectedNewLocationId();
+ Microsoft::Windows::Storage::Pickers::PickerViewMode GetSelectedNewViewMode();
+ std::vector GetFileFilters();
+ };
+}
+
+namespace winrt::FilePickersAppSinglePackaged::factory_implementation
+{
+ struct MainWindow : MainWindowT
+ {
+ };
+}
diff --git a/Samples/StoragePickers/cpp-sample/Package.appxmanifest b/Samples/StoragePickers/cpp-sample/Package.appxmanifest
new file mode 100644
index 000000000..40858e125
--- /dev/null
+++ b/Samples/StoragePickers/cpp-sample/Package.appxmanifest
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+ FilePickersAppSinglePackaged
+ xiaomgao
+ Assets\StoreLogo.png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/StoragePickers/cpp-sample/app.manifest b/Samples/StoragePickers/cpp-sample/app.manifest
new file mode 100644
index 000000000..f56549697
--- /dev/null
+++ b/Samples/StoragePickers/cpp-sample/app.manifest
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PerMonitorV2
+
+
+
\ No newline at end of file
diff --git a/Samples/StoragePickers/cpp-sample/packages.config b/Samples/StoragePickers/cpp-sample/packages.config
new file mode 100644
index 000000000..5ad1c12a7
--- /dev/null
+++ b/Samples/StoragePickers/cpp-sample/packages.config
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/StoragePickers/cpp-sample/pch.cpp b/Samples/StoragePickers/cpp-sample/pch.cpp
new file mode 100644
index 000000000..1d9f38c57
--- /dev/null
+++ b/Samples/StoragePickers/cpp-sample/pch.cpp
@@ -0,0 +1 @@
+#include "pch.h"
diff --git a/Samples/StoragePickers/cpp-sample/pch.h b/Samples/StoragePickers/cpp-sample/pch.h
new file mode 100644
index 000000000..294c200b5
--- /dev/null
+++ b/Samples/StoragePickers/cpp-sample/pch.h
@@ -0,0 +1,27 @@
+#pragma once
+#include
+#include
+#include
+#include
+
+// Undefine GetCurrentTime macro to prevent
+// conflict with Storyboard::GetCurrentTime
+#undef GetCurrentTime
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
\ No newline at end of file
diff --git a/Samples/StoragePickers/cs-sample/App.xaml b/Samples/StoragePickers/cs-sample/App.xaml
new file mode 100644
index 000000000..5a11fec41
--- /dev/null
+++ b/Samples/StoragePickers/cs-sample/App.xaml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/StoragePickers/cs-sample/App.xaml.cs b/Samples/StoragePickers/cs-sample/App.xaml.cs
new file mode 100644
index 000000000..2411ed5df
--- /dev/null
+++ b/Samples/StoragePickers/cs-sample/App.xaml.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices.WindowsRuntime;
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Controls;
+using Microsoft.UI.Xaml.Controls.Primitives;
+using Microsoft.UI.Xaml.Data;
+using Microsoft.UI.Xaml.Input;
+using Microsoft.UI.Xaml.Media;
+using Microsoft.UI.Xaml.Navigation;
+using Microsoft.UI.Xaml.Shapes;
+using Windows.ApplicationModel;
+using Windows.ApplicationModel.Activation;
+using Windows.Foundation;
+using Windows.Foundation.Collections;
+
+// To learn more about WinUI, the WinUI project structure,
+// and more about our project templates, see: http://aka.ms/winui-project-info.
+
+namespace FilePickersAppSinglePackaged
+{
+ ///
+ /// Provides application-specific behavior to supplement the default Application class.
+ ///
+ public partial class App : Application
+ {
+ private Window? _window;
+
+ ///
+ /// Initializes the singleton application object. This is the first line of authored code
+ /// executed, and as such is the logical equivalent of main() or WinMain().
+ ///
+ public App()
+ {
+ InitializeComponent();
+ }
+
+ ///
+ /// Invoked when the application is launched.
+ ///
+ /// Details about the launch request and process.
+ protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
+ {
+ _window = new MainWindow();
+ _window.Activate();
+ }
+ }
+}
diff --git a/Samples/StoragePickers/cs-sample/Assets/LockScreenLogo.scale-200.png b/Samples/StoragePickers/cs-sample/Assets/LockScreenLogo.scale-200.png
new file mode 100644
index 000000000..7440f0d4b
Binary files /dev/null and b/Samples/StoragePickers/cs-sample/Assets/LockScreenLogo.scale-200.png differ
diff --git a/Samples/StoragePickers/cs-sample/Assets/SplashScreen.scale-200.png b/Samples/StoragePickers/cs-sample/Assets/SplashScreen.scale-200.png
new file mode 100644
index 000000000..32f486a86
Binary files /dev/null and b/Samples/StoragePickers/cs-sample/Assets/SplashScreen.scale-200.png differ
diff --git a/Samples/StoragePickers/cs-sample/Assets/Square150x150Logo.scale-200.png b/Samples/StoragePickers/cs-sample/Assets/Square150x150Logo.scale-200.png
new file mode 100644
index 000000000..53ee3777e
Binary files /dev/null and b/Samples/StoragePickers/cs-sample/Assets/Square150x150Logo.scale-200.png differ
diff --git a/Samples/StoragePickers/cs-sample/Assets/Square44x44Logo.scale-200.png b/Samples/StoragePickers/cs-sample/Assets/Square44x44Logo.scale-200.png
new file mode 100644
index 000000000..f713bba67
Binary files /dev/null and b/Samples/StoragePickers/cs-sample/Assets/Square44x44Logo.scale-200.png differ
diff --git a/Samples/StoragePickers/cs-sample/Assets/Square44x44Logo.targetsize-24_altform-unplated.png b/Samples/StoragePickers/cs-sample/Assets/Square44x44Logo.targetsize-24_altform-unplated.png
new file mode 100644
index 000000000..dc9f5bea0
Binary files /dev/null and b/Samples/StoragePickers/cs-sample/Assets/Square44x44Logo.targetsize-24_altform-unplated.png differ
diff --git a/Samples/StoragePickers/cs-sample/Assets/StoreLogo.png b/Samples/StoragePickers/cs-sample/Assets/StoreLogo.png
new file mode 100644
index 000000000..a4586f26b
Binary files /dev/null and b/Samples/StoragePickers/cs-sample/Assets/StoreLogo.png differ
diff --git a/Samples/StoragePickers/cs-sample/Assets/Wide310x150Logo.scale-200.png b/Samples/StoragePickers/cs-sample/Assets/Wide310x150Logo.scale-200.png
new file mode 100644
index 000000000..8b4a5d0dd
Binary files /dev/null and b/Samples/StoragePickers/cs-sample/Assets/Wide310x150Logo.scale-200.png differ
diff --git a/Samples/StoragePickers/cs-sample/FilePickersAppSinglePackaged.csproj b/Samples/StoragePickers/cs-sample/FilePickersAppSinglePackaged.csproj
new file mode 100644
index 000000000..c987cb7ca
--- /dev/null
+++ b/Samples/StoragePickers/cs-sample/FilePickersAppSinglePackaged.csproj
@@ -0,0 +1,72 @@
+
+
+ WinExe
+ net8.0-windows10.0.19041.0
+ 10.0.17763.0
+ FilePickersAppSinglePackaged
+ app.manifest
+ x86;x64;ARM64
+ win-x86;win-x64;win-arm64
+ win-$(Platform).pubxml
+ true
+ true
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+ False
+ True
+ False
+ True
+ False
+ True
+ FilePickersAppSinglePackaged_TemporaryKey.pfx
+ SHA256
+ True
+ True
+ Never
+ 0
+
+
\ No newline at end of file
diff --git a/Samples/StoragePickers/cs-sample/FilePickersAppSinglePackaged.sln b/Samples/StoragePickers/cs-sample/FilePickersAppSinglePackaged.sln
new file mode 100644
index 000000000..6082d3de0
--- /dev/null
+++ b/Samples/StoragePickers/cs-sample/FilePickersAppSinglePackaged.sln
@@ -0,0 +1,43 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.14.36401.2 d17.14
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FilePickersAppSinglePackaged", "FilePickersAppSinglePackaged.csproj", "{EF931EC9-5781-40C7-8395-8B7FE01E146D}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|ARM64 = Debug|ARM64
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|ARM64 = Release|ARM64
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {EF931EC9-5781-40C7-8395-8B7FE01E146D}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {EF931EC9-5781-40C7-8395-8B7FE01E146D}.Debug|ARM64.Build.0 = Debug|ARM64
+ {EF931EC9-5781-40C7-8395-8B7FE01E146D}.Debug|ARM64.Deploy.0 = Debug|ARM64
+ {EF931EC9-5781-40C7-8395-8B7FE01E146D}.Debug|x64.ActiveCfg = Debug|x64
+ {EF931EC9-5781-40C7-8395-8B7FE01E146D}.Debug|x64.Build.0 = Debug|x64
+ {EF931EC9-5781-40C7-8395-8B7FE01E146D}.Debug|x64.Deploy.0 = Debug|x64
+ {EF931EC9-5781-40C7-8395-8B7FE01E146D}.Debug|x86.ActiveCfg = Debug|x86
+ {EF931EC9-5781-40C7-8395-8B7FE01E146D}.Debug|x86.Build.0 = Debug|x86
+ {EF931EC9-5781-40C7-8395-8B7FE01E146D}.Debug|x86.Deploy.0 = Debug|x86
+ {EF931EC9-5781-40C7-8395-8B7FE01E146D}.Release|ARM64.ActiveCfg = Release|ARM64
+ {EF931EC9-5781-40C7-8395-8B7FE01E146D}.Release|ARM64.Build.0 = Release|ARM64
+ {EF931EC9-5781-40C7-8395-8B7FE01E146D}.Release|ARM64.Deploy.0 = Release|ARM64
+ {EF931EC9-5781-40C7-8395-8B7FE01E146D}.Release|x64.ActiveCfg = Release|x64
+ {EF931EC9-5781-40C7-8395-8B7FE01E146D}.Release|x64.Build.0 = Release|x64
+ {EF931EC9-5781-40C7-8395-8B7FE01E146D}.Release|x64.Deploy.0 = Release|x64
+ {EF931EC9-5781-40C7-8395-8B7FE01E146D}.Release|x86.ActiveCfg = Release|x86
+ {EF931EC9-5781-40C7-8395-8B7FE01E146D}.Release|x86.Build.0 = Release|x86
+ {EF931EC9-5781-40C7-8395-8B7FE01E146D}.Release|x86.Deploy.0 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {635ACFB4-9E53-4940-82CC-B3A3314A4FCD}
+ EndGlobalSection
+EndGlobal
diff --git a/Samples/StoragePickers/cs-sample/MainWindow.xaml b/Samples/StoragePickers/cs-sample/MainWindow.xaml
new file mode 100644
index 000000000..4ea5482cf
--- /dev/null
+++ b/Samples/StoragePickers/cs-sample/MainWindow.xaml
@@ -0,0 +1,180 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/StoragePickers/cs-sample/MainWindow.xaml.cs b/Samples/StoragePickers/cs-sample/MainWindow.xaml.cs
new file mode 100644
index 000000000..9aaf39839
--- /dev/null
+++ b/Samples/StoragePickers/cs-sample/MainWindow.xaml.cs
@@ -0,0 +1,299 @@
+using Microsoft.UI.Xaml;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices.WindowsRuntime;
+using System.Text;
+using System.Text.Json.Serialization;
+
+// To learn more about WinUI, the WinUI project structure,
+// and more about our project templates, see: http://aka.ms/winui-project-info.
+
+namespace FilePickersAppSinglePackaged
+{
+
+ [JsonSerializable(typeof(Dictionary>))]
+ internal partial class SourceGenerationContext : JsonSerializerContext
+ {
+ }
+
+ public sealed partial class MainWindow : Window
+ {
+ public MainWindow()
+ {
+ this.InitializeComponent();
+ Title = "File Pickers Sample App";
+
+ // Set window size to make it taller
+ this.AppWindow.Resize(new Windows.Graphics.SizeInt32(1800, 1100));
+ }
+
+ #region Helper Methods
+
+ private void LogResult(string message)
+ {
+ ResultsTextBlock.Text = $"[{DateTime.Now:HH:mm:ss}] {message}\n{ResultsTextBlock.Text}";
+ }
+
+ private Microsoft.Windows.Storage.Pickers.PickerLocationId GetSelectedNewLocationId()
+ {
+ switch (StartLocationComboBox.SelectedIndex)
+ {
+ case 0: return Microsoft.Windows.Storage.Pickers.PickerLocationId.DocumentsLibrary;
+ case 1: return Microsoft.Windows.Storage.Pickers.PickerLocationId.ComputerFolder;
+ case 2: return Microsoft.Windows.Storage.Pickers.PickerLocationId.Desktop;
+ case 3: return Microsoft.Windows.Storage.Pickers.PickerLocationId.Downloads;
+
+ // HomeGroup is excluded from the new PickerLocationId enum. This example demonstrates how the error would look like.
+ case 4: return (Microsoft.Windows.Storage.Pickers.PickerLocationId)4;
+
+ case 5: return Microsoft.Windows.Storage.Pickers.PickerLocationId.MusicLibrary;
+ case 6: return Microsoft.Windows.Storage.Pickers.PickerLocationId.PicturesLibrary;
+ case 7: return Microsoft.Windows.Storage.Pickers.PickerLocationId.VideosLibrary;
+ case 8: return Microsoft.Windows.Storage.Pickers.PickerLocationId.Objects3D;
+ case 9: return Microsoft.Windows.Storage.Pickers.PickerLocationId.Unspecified;
+ case 10: return (Microsoft.Windows.Storage.Pickers.PickerLocationId)10;
+ default: throw new InvalidOperationException("Invalid location selected");
+ }
+ }
+
+ private Microsoft.Windows.Storage.Pickers.PickerViewMode GetSelectedNewViewMode()
+ {
+ switch (ViewModeComboBox.SelectedIndex)
+ {
+ case 0: return Microsoft.Windows.Storage.Pickers.PickerViewMode.List;
+ case 1: return Microsoft.Windows.Storage.Pickers.PickerViewMode.Thumbnail;
+ case 2: return (Microsoft.Windows.Storage.Pickers.PickerViewMode)2;
+ default: throw new InvalidOperationException("Invalid view mode selected");
+ }
+ }
+
+ private string[] GetFileFilters()
+ {
+ string input = FileTypeFilterInput.Text?.Trim() ?? "";
+ if (string.IsNullOrEmpty(input))
+ return ["*"];
+
+ return input.Split([','], StringSplitOptions.RemoveEmptyEntries)
+ .Select(s => s.Trim())
+ .ToArray();
+ }
+
+ #endregion
+
+ #region FileOpenPicker Tests
+
+ private async void NewPickSingleFile_Click(object sender, RoutedEventArgs e)
+ {
+ try
+ {
+ // Initialize new picker with AppWindow.Id
+ // for console apps, use the `default` as app window id, for instance:
+ // var picker = new Microsoft.Windows.Storage.Pickers.FileOpenPicker(default);
+ var picker = new Microsoft.Windows.Storage.Pickers.FileOpenPicker(this.AppWindow.Id);
+
+ if (CommitButtonCheckBox.IsChecked == true)
+ {
+ picker.CommitButtonText = CommitButtonTextInput.Text;
+ }
+
+ if (ViewModeCheckBox.IsChecked == true)
+ {
+ picker.ViewMode = GetSelectedNewViewMode();
+ }
+
+ if (SuggestedStartLocationCheckBox.IsChecked == true)
+ {
+ picker.SuggestedStartLocation = GetSelectedNewLocationId();
+ }
+
+ if (FileTypeFilterCheckBox.IsChecked == true)
+ {
+ foreach (var filter in GetFileFilters())
+ {
+ picker.FileTypeFilter.Add(filter);
+ }
+ }
+
+ var result = await picker.PickSingleFileAsync();
+ if (result != null)
+ {
+ LogResult($"New FileOpenPicker - PickSingleFileAsync:\nFile: {System.IO.Path.GetFileName(result.Path)}\nPath: {result.Path}");
+ }
+ else
+ {
+ LogResult("New FileOpenPicker - PickSingleFileAsync: Operation cancelled");
+ }
+ }
+ catch (Exception ex)
+ {
+ LogResult($"Error in New FileOpenPicker: {ex.Message}");
+ }
+ }
+
+ private async void NewPickMultipleFiles_Click(object sender, RoutedEventArgs e)
+ {
+ try
+ {
+ // Initialize new picker with AppWindow.Id
+ // for console apps, use the `default` as app window id, for instance:
+ // var picker = new Microsoft.Windows.Storage.Pickers.FileOpenPicker(default);
+ var picker = new Microsoft.Windows.Storage.Pickers.FileOpenPicker(this.AppWindow.Id);
+
+ if (CommitButtonCheckBox.IsChecked == true)
+ {
+ picker.CommitButtonText = CommitButtonTextInput.Text;
+ }
+
+ if (ViewModeCheckBox.IsChecked == true)
+ {
+ picker.ViewMode = GetSelectedNewViewMode();
+ }
+
+ if (SuggestedStartLocationCheckBox.IsChecked == true)
+ {
+ picker.SuggestedStartLocation = GetSelectedNewLocationId();
+ }
+
+ if (FileTypeFilterCheckBox.IsChecked == true)
+ {
+ foreach (var filter in GetFileFilters())
+ {
+ picker.FileTypeFilter.Add(filter);
+ }
+ }
+
+ var results = await picker.PickMultipleFilesAsync();
+ if (results != null && results.Count > 0)
+ {
+ var sb = new StringBuilder($"New FileOpenPicker - PickMultipleFilesAsync: {results.Count} files\n");
+ foreach (var result in results)
+ {
+ sb.AppendLine($"- {System.IO.Path.GetFileName(result.Path)}: {result.Path}");
+ }
+ LogResult(sb.ToString());
+ }
+ else
+ {
+ LogResult("New FileOpenPicker - PickMultipleFilesAsync: Operation cancelled or no files selected");
+ }
+ }
+ catch (Exception ex)
+ {
+ LogResult($"Error in New PickMultipleFilesAsync: {ex.Message}");
+ }
+ }
+
+ #endregion
+
+ #region FileSavePicker Tests
+
+ private async void NewPickSaveFile_Click(object sender, RoutedEventArgs e)
+ {
+ try
+ {
+ // Initialize new picker with AppWindow.Id
+ // for console apps, use the `default` as app window id, for instance:
+ // var picker = new Microsoft.Windows.Storage.Pickers.FileSavePicker(default);
+ var picker = new Microsoft.Windows.Storage.Pickers.FileSavePicker(this.AppWindow.Id);
+
+ if (SuggestedFileNameCheckBox.IsChecked == true)
+ {
+ picker.SuggestedFileName = SuggestedFileNameInput.Text;
+ }
+
+ if (DefaultFileExtensionCheckBox.IsChecked == true)
+ {
+ picker.DefaultFileExtension = DefaultFileExtensionInput.Text;
+ }
+
+ if (SuggestedFolderCheckBox.IsChecked == true)
+ {
+ picker.SuggestedFolder = SuggestedFolderInput.Text;
+ }
+
+ if (FileTypeChoicesCheckBox.IsChecked == true)
+ {
+ var choicesJson = (string)FileTypeChoicesInput.Text;
+ if (!string.IsNullOrEmpty(choicesJson))
+ {
+ var choices = System.Text.Json.JsonSerializer.Deserialize(choicesJson, SourceGenerationContext.Default.DictionaryStringListString);
+ if (choices != null)
+ {
+ foreach (var choice in choices)
+ {
+ picker.FileTypeChoices.Add(choice.Key, choice.Value);
+ }
+ }
+ }
+ }
+
+ if (CommitButtonCheckBox.IsChecked == true)
+ {
+ picker.CommitButtonText = CommitButtonTextInput.Text;
+ }
+
+ if (SuggestedStartLocationCheckBox.IsChecked == true)
+ {
+ picker.SuggestedStartLocation = GetSelectedNewLocationId();
+ }
+
+ var result = await picker.PickSaveFileAsync();
+ if (result != null)
+ {
+ LogResult($"New FileSavePicker picked file: \n{System.IO.Path.GetFileName(result.Path)}\nPath: {result.Path}");
+ }
+ else
+ {
+ LogResult("New FileSavePicker with FileTypeChoices\nOperation cancelled");
+ }
+ }
+ catch (Exception ex)
+ {
+ LogResult($"Error in New FileTypeChoices: {ex.Message}");
+ }
+ }
+
+ #endregion
+
+ #region FolderPicker Tests
+
+ private async void NewPickFolder_Click(object sender, RoutedEventArgs e)
+ {
+ try
+ {
+ // Initialize new picker with AppWindow.Id
+ // for console apps, use the `default` as app window id, for instance:
+ // var picker = new Microsoft.Windows.Storage.Pickers.FolderPicker(default);
+ var picker = new Microsoft.Windows.Storage.Pickers.FolderPicker(this.AppWindow.Id);
+
+ if (CommitButtonCheckBox.IsChecked == true)
+ {
+ picker.CommitButtonText = CommitButtonTextInput.Text;
+ }
+
+ if (SuggestedStartLocationCheckBox.IsChecked == true)
+ {
+ picker.SuggestedStartLocation = GetSelectedNewLocationId();
+ }
+
+ var result = await picker.PickSingleFolderAsync();
+ if (result != null)
+ {
+ LogResult($"New FolderPicker - PickSingleFolderAsync:\nFolder: {System.IO.Path.GetFileName(result.Path)}\nPath: {result.Path}");
+ }
+ else
+ {
+ LogResult("New FolderPicker - PickSingleFolderAsync: Operation cancelled");
+ }
+ }
+ catch (Exception ex)
+ {
+ LogResult($"Error in New FolderPicker: {ex.Message}");
+ }
+ }
+
+ #endregion
+ }
+
+}
diff --git a/Samples/StoragePickers/cs-sample/Package.appxmanifest b/Samples/StoragePickers/cs-sample/Package.appxmanifest
new file mode 100644
index 000000000..501de98c9
--- /dev/null
+++ b/Samples/StoragePickers/cs-sample/Package.appxmanifest
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+ FilePickersAppSinglePackaged
+ xiaomgao
+ Assets\StoreLogo.png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/StoragePickers/cs-sample/Properties/PublishProfiles/FolderProfile.pubxml b/Samples/StoragePickers/cs-sample/Properties/PublishProfiles/FolderProfile.pubxml
new file mode 100644
index 000000000..ca2c25558
--- /dev/null
+++ b/Samples/StoragePickers/cs-sample/Properties/PublishProfiles/FolderProfile.pubxml
@@ -0,0 +1,11 @@
+
+
+
+
+ Release
+ ARM64
+ bin\\\win-x64\publish\win-x64\
+ FileSystem
+ <_TargetId>Folder
+
+
\ No newline at end of file
diff --git a/Samples/StoragePickers/cs-sample/Properties/PublishProfiles/win-arm64.pubxml b/Samples/StoragePickers/cs-sample/Properties/PublishProfiles/win-arm64.pubxml
new file mode 100644
index 000000000..f361bfe8f
--- /dev/null
+++ b/Samples/StoragePickers/cs-sample/Properties/PublishProfiles/win-arm64.pubxml
@@ -0,0 +1,18 @@
+
+
+
+
+ FileSystem
+ ARM64
+ win-arm64
+ bin\\\win-arm64\publish\win-arm64\
+ true
+ false
+ Release
+ net8.0-windows10.0.19041.0
+ false
+ false
+
+
\ No newline at end of file
diff --git a/Samples/StoragePickers/cs-sample/Properties/PublishProfiles/win-x64.pubxml b/Samples/StoragePickers/cs-sample/Properties/PublishProfiles/win-x64.pubxml
new file mode 100644
index 000000000..e3e688695
--- /dev/null
+++ b/Samples/StoragePickers/cs-sample/Properties/PublishProfiles/win-x64.pubxml
@@ -0,0 +1,18 @@
+
+
+
+
+ FileSystem
+ x64
+ win-x64
+ bin\\\win-x64\publish\
+ true
+ false
+ Release
+ net8.0-windows10.0.19041.0
+ false
+ false
+
+
\ No newline at end of file
diff --git a/Samples/StoragePickers/cs-sample/Properties/PublishProfiles/win-x86.pubxml b/Samples/StoragePickers/cs-sample/Properties/PublishProfiles/win-x86.pubxml
new file mode 100644
index 000000000..a70c69425
--- /dev/null
+++ b/Samples/StoragePickers/cs-sample/Properties/PublishProfiles/win-x86.pubxml
@@ -0,0 +1,14 @@
+
+
+
+
+ FileSystem
+ x86
+ win-x86
+ bin\$(Configuration)\$(TargetFramework)\$(RuntimeIdentifier)\publish\
+ true
+ False
+
+
\ No newline at end of file
diff --git a/Samples/StoragePickers/cs-sample/Properties/launchSettings.json b/Samples/StoragePickers/cs-sample/Properties/launchSettings.json
new file mode 100644
index 000000000..e0c0ad43a
--- /dev/null
+++ b/Samples/StoragePickers/cs-sample/Properties/launchSettings.json
@@ -0,0 +1,10 @@
+{
+ "profiles": {
+ "FilePickersAppSinglePackaged (Package)": {
+ "commandName": "MsixPackage"
+ },
+ "FilePickersAppSinglePackaged (Unpackaged)": {
+ "commandName": "Project"
+ }
+ }
+}
\ No newline at end of file
diff --git a/Samples/StoragePickers/cs-sample/app.manifest b/Samples/StoragePickers/cs-sample/app.manifest
new file mode 100644
index 000000000..f56549697
--- /dev/null
+++ b/Samples/StoragePickers/cs-sample/app.manifest
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PerMonitorV2
+
+
+
\ No newline at end of file
diff --git a/Samples/StoragePickers/images/deploy1.png b/Samples/StoragePickers/images/deploy1.png
new file mode 100644
index 000000000..8a6367c1a
Binary files /dev/null and b/Samples/StoragePickers/images/deploy1.png differ
diff --git a/Samples/StoragePickers/images/deploy10.png b/Samples/StoragePickers/images/deploy10.png
new file mode 100644
index 000000000..0bd1c3169
Binary files /dev/null and b/Samples/StoragePickers/images/deploy10.png differ
diff --git a/Samples/StoragePickers/images/deploy2.png b/Samples/StoragePickers/images/deploy2.png
new file mode 100644
index 000000000..927df22ef
Binary files /dev/null and b/Samples/StoragePickers/images/deploy2.png differ
diff --git a/Samples/StoragePickers/images/deploy3.png b/Samples/StoragePickers/images/deploy3.png
new file mode 100644
index 000000000..c25e7e927
Binary files /dev/null and b/Samples/StoragePickers/images/deploy3.png differ
diff --git a/Samples/StoragePickers/images/deploy4.png b/Samples/StoragePickers/images/deploy4.png
new file mode 100644
index 000000000..2ce2b4950
Binary files /dev/null and b/Samples/StoragePickers/images/deploy4.png differ
diff --git a/Samples/StoragePickers/images/deploy5.png b/Samples/StoragePickers/images/deploy5.png
new file mode 100644
index 000000000..6072709d0
Binary files /dev/null and b/Samples/StoragePickers/images/deploy5.png differ
diff --git a/Samples/StoragePickers/images/deploy6.png b/Samples/StoragePickers/images/deploy6.png
new file mode 100644
index 000000000..8f6315cf8
Binary files /dev/null and b/Samples/StoragePickers/images/deploy6.png differ
diff --git a/Samples/StoragePickers/images/deploy7.png b/Samples/StoragePickers/images/deploy7.png
new file mode 100644
index 000000000..3cd0ffc7f
Binary files /dev/null and b/Samples/StoragePickers/images/deploy7.png differ
diff --git a/Samples/StoragePickers/images/deploy8.png b/Samples/StoragePickers/images/deploy8.png
new file mode 100644
index 000000000..bd735be89
Binary files /dev/null and b/Samples/StoragePickers/images/deploy8.png differ
diff --git a/Samples/StoragePickers/images/deploy9.png b/Samples/StoragePickers/images/deploy9.png
new file mode 100644
index 000000000..97832ba63
Binary files /dev/null and b/Samples/StoragePickers/images/deploy9.png differ
diff --git a/Samples/StoragePickers/images/screenshot-storage-pickers.png b/Samples/StoragePickers/images/screenshot-storage-pickers.png
new file mode 100644
index 000000000..f123907f2
Binary files /dev/null and b/Samples/StoragePickers/images/screenshot-storage-pickers.png differ