{"id":44719,"date":"2023-03-20T11:05:00","date_gmt":"2023-03-20T19:05:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/dotnet\/?p=44719"},"modified":"2023-03-14T02:01:18","modified_gmt":"2023-03-14T10:01:18","slug":"file-and-folder-dialogs-communitytoolkit","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/file-and-folder-dialogs-communitytoolkit\/","title":{"rendered":"File and Folder dialogs in .NET MAUI with CommunityToolkit"},"content":{"rendered":"<blockquote><p>Note: This is a guest blog post by Vladislav Antonyuk, who is a senior software engineer at DataArt and a core contributor of the .NET MAUI Community Toolkit.<\/p><\/blockquote>\n<p>Interacting with files and folders is a routine task for countless applications, yet it often involves writing tedious platform-specific code.<\/p>\n<p>The good news is that the new <a href=\"https:\/\/github.com\/CommunityToolkit\/Maui\">CommunityToolkit.Maui<\/a> <a href=\"https:\/\/github.com\/CommunityToolkit\/Maui\/releases\/tag\/5.0.0\">version 5.0<\/a> now contains the enhanced versions of <code>FolderPicker<\/code> and <code>FileSaver<\/code> classes which provide an easy way to select target folders and save files to the filesystem across all the .NET MAUI platforms.<\/p>\n<h2>FileSaver<\/h2>\n<p>By using <code>FileSaver<\/code>, your application can offer users a convenient dialog that allows them to choose a destination folder. With only a few lines of code, you can then save any file type, including documents, images, videos, and more.<\/p>\n<p>Here&#8217;s an example of how you can use <code>FileSaver<\/code> in C#:<\/p>\n<pre><code class=\"language-csharp\">using var stream = new MemoryStream(Encoding.Default.GetBytes(\"Hello from the Community Toolkit!\"));\r\nvar fileSaveResult = await FileSaver.Default.SaveAsync(\"sample.txt\", stream, cancellationToken);\r\nif (fileSaveResult.IsSuccessful)\r\n{\r\n    await Toast.Make($\"File is saved: {fileSaveResult.FilePath}\").Show(cancellationToken);\r\n}\r\nelse\r\n{\r\n    await Toast.Make($\"File is not saved, {fileSaveResult.Exception.Message}\").Show(cancellationToken);\r\n}<\/code><\/pre>\n<p>This code opens a filesystem dialog, that allows the user to choose the target file location, creates a new file called &#8220;sample.txt&#8221; and writes a stream with the text &#8220;Hello from the Community Toolkit!&#8221; to it. Users can also change the file name to suit their needs.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2023\/03\/Picture1.png\" alt=\"FileSaver Dialog on Windows\" \/><\/p>\n<p><code>FileSaver<\/code> catches all exceptions and returns the operation result. However, if you would like to handle only specific exceptions like the user cancels the operation, you can wrap code in a try\/catch and call the <code>EnsureSuccess<\/code> method:<\/p>\n<pre><code class=\"language-csharp\">using var stream = new MemoryStream(Encoding.Default.GetBytes(\"Hello from the Community Toolkit!\"));\r\ntry\r\n{\r\n    var fileSaverResult = await FileSaver.SaveAsync(\"initial-path\", \"sample.txt\", stream, cancellationToken);\r\n    fileSaverResult.EnsureSuccess();\r\n\r\n    await Toast.Make($\"File is saved: {fileSaverResult.FilePath}\").Show(cancellationToken);\r\n}\r\ncatch (Exception ex)\r\n{\r\n    await Toast.Make($\"File is not saved, {ex.Message}\").Show(cancellationToken);\r\n}<\/code><\/pre>\n<p>A more complete example of using <code>FileSaver<\/code> is in my <a href=\"https:\/\/github.com\/VladislavAntonyuk\/MauiSamples\/tree\/main\/MauiPaint\">MauiPaint<\/a> sample application. This is how it works on <code>macOS<\/code>:<\/p>\n<p><div style=\"width: 640px;\" class=\"wp-video\"><video class=\"wp-video-shortcode\" id=\"video-44719-1\" width=\"640\" height=\"360\" preload=\"metadata\" controls=\"controls\"><source type=\"video\/mp4\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2023\/02\/FileSaverMacCatalyst.mp4?_=1\" \/><a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2023\/02\/FileSaverMacCatalyst.mp4\">https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2023\/02\/FileSaverMacCatalyst.mp4<\/a><\/video><\/div><\/p>\n<blockquote><p>Note: Android Developers should provide permission to work with file storage.<\/p>\n<pre><code class=\"language-xml\">&lt;uses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\" \/&gt;\r\n&lt;uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\" \/&gt;<\/code><\/pre>\n<\/blockquote>\n<h2>FolderPicker<\/h2>\n<p><code>FolderPicker<\/code> is another powerful capability that can be found as part of <a href=\"https:\/\/github.com\/CommunityToolkit\/Maui\">CommunityToolkit.Maui<\/a> which allows users to select folders in the filesystem using a UI dialog. With <code>FolderPicker<\/code> developers can easily get information about the selected folder such as its name and path.<\/p>\n<p>Here&#8217;s an example of how <code>FolderPicker<\/code> can be used in C#:<\/p>\n<pre><code class=\"language-csharp\">var folderPickerResult = await folderPicker.PickAsync(cancellationToken);\r\nif (folderPickerResult.IsSuccessful)\r\n{\r\n    await Toast.Make($\"Folder picked: Name - {folderPickerResult.Folder.Name}, Path - {folderPickerResult.Folder.Path}\", ToastDuration.Long).Show(cancellationToken);\r\n}\r\nelse\r\n{\r\n    await Toast.Make($\"Folder is not picked, {folderPickerResult.Exception.Message}\").Show(cancellationToken);\r\n}<\/code><\/pre>\n<p>This code prompts the user to select a folder, and the result of the operation will be stored in the &#8220;folderPickerResult&#8221; variable.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2023\/03\/Picture2.png\" alt=\"FolderPicker Dialog on Windows\" \/><\/p>\n<p>Again, it&#8217;s a good idea to wrap in a try\/catch in case you prefer to use the <code>EnsureSuccess<\/code> method:<\/p>\n<pre><code class=\"language-csharp\">try\r\n{\r\n    var folderPickerResult = await FolderPicker.Default.PickAsync(\"initial-path\", cancellationToken);\r\n    folderPickerResult.EnsureSuccess();\r\n    await Toast.Make($\"Folder picked: Name - {folderPickerResult.Folder.Name}, Path - {folderPickerResult.Folder.Path}\", ToastDuration.Long).Show(cancellationToken);\r\n}\r\ncatch (Exception ex)\r\n{\r\n    await Toast.Make($\"Folder is not picked, {ex.Message}\").Show(cancellationToken);\r\n}<\/code><\/pre>\n<blockquote><p>Note: Android Developers should provide permission to work with file storage.<\/p>\n<pre><code class=\"language-xml\">&lt;uses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\" \/&gt;<\/code><\/pre>\n<\/blockquote>\n<h2>Summary<\/h2>\n<p><code>FileSaver<\/code> and <code>FolderPicker<\/code> are two powerful new tools that can be found as part of the <a href=\"https:\/\/github.com\/CommunityToolkit\/Maui\">CommunityToolkit.Maui<\/a> library. They make it easy for developers to collaborate with the filesystem to manage the files and folders. As usual, further information about these two APIs can be found in the <a href=\"https:\/\/learn.microsoft.com\/dotnet\/communitytoolkit\/maui\/essentials\/\">documentation<\/a>.<\/p>\n<p>If you&#8217;re a developer working with C# and .NET MAUI, give them a try today and see how they can help get better integration with the OS filesystem.<\/p>\n<p>Finally, be sure to check out the full <a href=\"https:\/\/github.com\/CommunityToolkit\/Maui\/releases\/tag\/5.0.0\">release notes for version 5.0<\/a> for even more great resources for .NET MAUI developers.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Effortlessly incorporate file system dialogs in your .NET MAUI applications.<\/p>\n","protected":false},"author":7499,"featured_media":44720,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[685,7233],"tags":[7238,7655,7246,7654,7245,7622,7702,7621],"class_list":["post-44719","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnet","category-maui","tag-net-maui","tag-net-maui-community-toolkit","tag-android","tag-community-toolkit","tag-ios","tag-macos","tag-tizen","tag-windows"],"acf":[],"blog_post_summary":"<p>Effortlessly incorporate file system dialogs in your .NET MAUI applications.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/44719","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/7499"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=44719"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/44719\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/44720"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=44719"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=44719"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=44719"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}