├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── SECURITY.md └── tasks ├── App-version-and-title.md ├── Bing-image-of-the-day-URI.md ├── Cancelling-a-task-after-a-delay.md ├── Capture-an-image.md ├── Clipboard-text.md ├── Color-names-and-contrasting-foregrounds.md ├── Color-names-and-contrasting-foregrounds.png ├── Colors-as-a-collection.md ├── Convert-DPI-rectangles.md ├── Convert-RGB-to-HSV.md ├── Convert-hex-to-color.md ├── Data-binding-change-notification.md ├── File-exists.md ├── Folder-access-preservation.md ├── InkCanvas-data-binding.md ├── Launch-executable.md ├── Location-of-device.md ├── Media-file-concatenation.md ├── Play-sound-once-or-looped.md ├── Show-dialog-box.md ├── Socket-programming-with-TCP.md ├── Socket-programming-with-UDP.md ├── Store-app-rating-pop-up.md ├── Thread-switching-within-a-task.md ├── Time-specific-salutation.md ├── UI-thread-access-from-background-thread.md ├── UI-thread-task-await-from-background-thread.md ├── UI-update-after-delay.md ├── UI-updates-with-a-timer.md └── User-info.md /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | We're not ready to accept contributions at this time, but if you have any feedback, please post to the Issues list. Thanks! 2 | 3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Microsoft 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Windows task snippets 2 | 3 | This repo collects snippets of ready-to-use code that accomplish small but useful tasks of 4 | interest to Universal Windows Platform (UWP) app developers. These snippets represent 5 | simple solutions to common problems, and simple recipes to help you implement new app features. 6 | 7 | Each snippet includes the using 8 | statements that it requires, which you can add to the top of your file as needed. 9 | 10 | Each snippet is written in C# unless otherwise indicated. 11 | 12 | For more UWP samples, see [Windows on GitHub](http://microsoft.github.io/windows/). 13 | 14 | ## Snippets 15 | 16 | ### Data binding 17 | 18 | [Data binding change notification](tasks/Data-binding-change-notification.md) 19 | [Data-bind an InkCanvas control](tasks/InkCanvas-data-binding.md) 20 | 21 | ### Files and folders 22 | 23 | [File exists](tasks/File-exists.md) 24 | [Preserve access to a folder](tasks/Folder-access-preservation.md) 25 | [Launch executable](tasks/Launch-executable.md) 26 | 27 | ### Colors 28 | 29 | [Color names and contrasting foregrounds](tasks/Color-names-and-contrasting-foregrounds.md) 30 | [Colors as a collection](tasks/Colors-as-a-collection.md) 31 | [Convert hex to color](tasks/Convert-hex-to-color.md) 32 | [Convert RGB to HSV](tasks/Convert-RGB-to-HSV.md) 33 | 34 | ### Images 35 | 36 | [Bing image-of-the-day URI](tasks/Bing-image-of-the-day-URI.md) 37 | [Capture an image](tasks/Capture-an-image.md) 38 | 39 | ### Media 40 | 41 | [Concatenate media files](tasks/Media-file-concatenation.md) 42 | [Play sound once or looped](tasks/Play-sound-once-or-looped.md) 43 | 44 | ### UI thread 45 | 46 | [UI thread access from background thread](tasks/UI-thread-access-from-background-thread.md) 47 | [UI thread task await from background thread](tasks/UI-thread-task-await-from-background-thread.md) 48 | [UI update after a delay](tasks/UI-update-after-delay.md) 49 | [UI updates with a timer](tasks/UI-updates-with-a-timer.md) 50 | [Thread switching within a task](tasks/Thread-switching-within-a-task.md) 51 | 52 | ### Tasks 53 | 54 | [Cancelling a task after a delay](tasks/Cancelling-a-task-after-a-delay.md) 55 | 56 | ### Sockets 57 | 58 | [Socket programming with TCP](tasks/Socket-programming-with-TCP.md) 59 | [Socket programming with UDP](tasks/Socket-programming-with-UDP.md) 60 | 61 | ### Popups 62 | [Show pop-up asking user to rate app](tasks/Store-app-rating-pop-up.md) 63 | [Show dialog box](tasks/Show-dialog-box.md) 64 | 65 | ### Miscellaneous 66 | 67 | [App version and title](tasks/App-version-and-title.md) 68 | [Clipboard text](tasks/Clipboard-text.md) 69 | [Get user info](tasks/User-info.md) 70 | [Convert the DPI of rectangles (C++)](tasks/Convert-DPI-rectangles.md) 71 | [Get a device's current location](tasks/Location-of-device.md) 72 | [Time-specific salutation](tasks/Time-specific-salutation.md) 73 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Security 4 | 5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). 6 | 7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below. 8 | 9 | ## Reporting Security Issues 10 | 11 | **Please do not report security vulnerabilities through public GitHub issues.** 12 | 13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report). 14 | 15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey). 16 | 17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). 18 | 19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: 20 | 21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) 22 | * Full paths of source file(s) related to the manifestation of the issue 23 | * The location of the affected source code (tag/branch/commit or direct URL) 24 | * Any special configuration required to reproduce the issue 25 | * Step-by-step instructions to reproduce the issue 26 | * Proof-of-concept or exploit code (if possible) 27 | * Impact of the issue, including how an attacker might exploit the issue 28 | 29 | This information will help us triage your report more quickly. 30 | 31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs. 32 | 33 | ## Preferred Languages 34 | 35 | We prefer all communications to be in English. 36 | 37 | ## Policy 38 | 39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd). 40 | 41 | 42 | -------------------------------------------------------------------------------- /tasks/App-version-and-title.md: -------------------------------------------------------------------------------- 1 | 5 | 6 | # Get app title and version info 7 | 8 | Gets the title and version of an app as specified in the project manifest. 9 | 10 | ```C# 11 | using Windows.ApplicationModel; 12 | 13 | public static string AppName 14 | { 15 | get { return Package.Current.Id.Name; } 16 | } 17 | 18 | public static string AppVersion 19 | { 20 | get 21 | { 22 | PackageVersion version = Package.Current.Id.Version; 23 | return $"{version.Major}.{version.Minor}.{version.Build}.{version.Revision}"; 24 | } 25 | } 26 | ``` 27 | 28 | ## See also 29 | 30 | [Package class](https://msdn.microsoft.com/library/windows/apps/windows.applicationmodel.package.aspx) 31 | [Interpolated strings](https://msdn.microsoft.com/library/dn961160.aspx) (strings with a $ prefix) 32 | -------------------------------------------------------------------------------- /tasks/Bing-image-of-the-day-URI.md: -------------------------------------------------------------------------------- 1 | 5 | 6 | # Get the Bing image of the day URI 7 | 8 | Gets the URI for the the Bing image of the day, optionally 9 | for the specified resolution and market. 10 | 11 | The market parameter defaults to "en-ww", which refers to "English - worldwide". 12 | For other values, see the [table of language codes](http://aka.ms/languagecodes). 13 | Some images may not be available in all markets. 14 | 15 | The resolution parameter defaults to Unspecified, which is typically 1366x768, but may 16 | vary for different images. Images may not be available in other resolutions, 17 | so any Resolution values other than Unspecified might not produce usable URLs. 18 | Also, there may be other resolutions available besides the ones in the Resolution 19 | enumeration below. 20 | 21 | ```C# 22 | using System; 23 | using System.Linq; 24 | using System.Threading.Tasks; 25 | using System.Xml.Linq; 26 | using Windows.Web.Http; 27 | 28 | public enum Resolution { Unspecified, _800x600, _1024x768, _1366x768, _1920x1080, _1920x1200 } 29 | 30 | public static async Task GetBingImageOfTheDayUriAsync( 31 | Resolution resolution = Resolution.Unspecified, 32 | string market = "en-ww") 33 | { 34 | var request = new Uri($"http://www.bing.com/hpimagearchive.aspx?n=1&mkt={market}"); 35 | string result = null; 36 | using (var httpClient = new HttpClient()) 37 | { 38 | result = await httpClient.GetStringAsync(request); 39 | } 40 | var targetElement = resolution == Resolution.Unspecified ? "url" : "urlBase"; 41 | var pathString = XDocument.Parse(result).Descendants(targetElement).First().Value; 42 | var resolutionString = resolution == Resolution.Unspecified ? "" : $"{resolution}.jpg"; 43 | return new Uri($"http://www.bing.com{pathString}{resolutionString}"); 44 | } 45 | ``` 46 | 47 | ## Usage 48 | 49 | ```C# 50 | private async void MainPage_Loaded(object sender, Windows.UI.Xaml.RoutedEventArgs e) 51 | { 52 | Image1.Source = new Windows.UI.Xaml.Media.Imaging.BitmapImage( 53 | await GetBingImageOfTheDayUriAsync()); 54 | } 55 | 56 | // Normally declared in XAML; included here so the snippet will compile. 57 | private Windows.UI.Xaml.Controls.Image Image1 = new Windows.UI.Xaml.Controls.Image(); 58 | ``` 59 | 60 | ## See also 61 | 62 | [HttpClient class](https://msdn.microsoft.com/library/windows/apps/windows.web.http.httpclient.aspx) 63 | [Uri class](https://msdn.microsoft.com/library/system.uri.aspx) 64 | [Interpolated strings](https://msdn.microsoft.com/library/dn961160.aspx) (strings with a $ prefix) 65 | [?: operator](https://msdn.microsoft.com/library/ty67wk28.aspx) 66 | -------------------------------------------------------------------------------- /tasks/Cancelling-a-task-after-a-delay.md: -------------------------------------------------------------------------------- 1 | 5 | 6 | # Cancelling a task after a delay 7 | 8 | Provides a convenient way to cancel a task if it 9 | runs longer than a specified period of time. 10 | 11 | ```C# 12 | using System; 13 | using System.Threading.Tasks; 14 | using Windows.Foundation; 15 | 16 | public static class Helpers 17 | { 18 | static async void CancelAfterHelper(IAsyncInfo info, TimeSpan delay) 19 | { 20 | await Task.Delay(delay); 21 | info.Cancel(); 22 | } 23 | 24 | public static IAsyncAction CancelAfter(this IAsyncAction action, TimeSpan delay) 25 | { 26 | CancelAfterHelper(action, delay); 27 | return action; 28 | } 29 | 30 | public static IAsyncOperation CancelAfter(this IAsyncOperation op, TimeSpan delay) 31 | { 32 | CancelAfterHelper(op, delay); 33 | return op; 34 | } 35 | } 36 | ``` 37 | 38 | ## Usage 39 | 40 | The following usage snippet shows how to display a dialog box for up to 30 seconds. 41 | 42 | ```C# 43 | using Windows.UI.Popups; 44 | using Windows.UI.Xaml; 45 | 46 | private async Task IsUserStillThereAsync() 47 | { 48 | var dialog = new MessageDialog("Are you still there?") 49 | { 50 | Commands = { new UICommand("Still here") } 51 | }; 52 | try 53 | { 54 | await dialog.ShowAsync().CancelAfter(TimeSpan.FromSeconds(30)); 55 | return true; // user responded to the dialog 56 | } 57 | catch (TaskCanceledException) 58 | { 59 | return false; // user did not respond to the dialog 60 | } 61 | } 62 | ``` 63 | 64 | ## See also 65 | 66 | [MessageDialog class](https://msdn.microsoft.com/library/windows/apps/br208674) 67 | [UICommand class](https://msdn.microsoft.com/library/windows/apps/windows.ui.popups.uicommand.aspx) 68 | -------------------------------------------------------------------------------- /tasks/Capture-an-image.md: -------------------------------------------------------------------------------- 1 | 5 | 6 | # Capture an image 7 | 8 | Captures an image using the device's camera and returns it as a bitmap. 9 | 10 | ```C# 11 | using System; 12 | using System.Threading.Tasks; 13 | using Windows.Media.Capture; 14 | using Windows.Storage; 15 | using Windows.Storage.Streams; 16 | using Windows.UI.Xaml.Controls; 17 | using Windows.UI.Xaml.Media.Imaging; 18 | 19 | public async Task CaptureImage(bool allowCropping = true, 20 | CameraCaptureUIPhotoFormat photoFormat = CameraCaptureUIPhotoFormat.Jpeg, 21 | CameraCaptureUIMaxPhotoResolution maxPhotoResolution = CameraCaptureUIMaxPhotoResolution.HighestAvailable) 22 | { 23 | var captureUI = new CameraCaptureUI(); 24 | captureUI.PhotoSettings.AllowCropping = allowCropping; 25 | captureUI.PhotoSettings.Format = photoFormat; 26 | captureUI.PhotoSettings.MaxResolution = maxPhotoResolution; 27 | StorageFile file = await captureUI.CaptureFileAsync(CameraCaptureUIMode.Photo); 28 | if (file == null) return null; 29 | using (IRandomAccessStream ras = await file.OpenAsync(FileAccessMode.Read)) 30 | { 31 | var bitmapImage = new BitmapImage(); 32 | bitmapImage.SetSource(ras); 33 | return bitmapImage; 34 | } 35 | } 36 | ``` 37 | 38 | ## Usage 39 | 40 | ```C# 41 | Image img = new Image 42 | { 43 | Source = await CaptureImage() 44 | }; 45 | ``` 46 | 47 | ## See also 48 | 49 | [CameraCaptureUI class](https://msdn.microsoft.com/library/windows/apps/xaml/windows.media.capture.cameracaptureui.aspx) 50 | [StorageFile class](https://msdn.microsoft.com/en-us/library/windows/apps/windows.storage.storagefile.aspx) 51 | [BitmapImage class](https://msdn.microsoft.com/library/windows/apps/windows.ui.xaml.media.imaging.bitmapimage.aspx) 52 | [Image class](https://msdn.microsoft.com/library/windows/apps/windows.ui.xaml.controls.image.aspx) 53 | -------------------------------------------------------------------------------- /tasks/Clipboard-text.md: -------------------------------------------------------------------------------- 1 | 5 | 6 | # Get or set clipboard text 7 | 8 | Gets or sets the current clipboard text. 9 | 10 | If the clipboard contains a non-text item (like an image), GetClipboardTextAsync returns an empty string. 11 | 12 | ```C# 13 | using System; 14 | using System.Threading.Tasks; 15 | using Windows.ApplicationModel.DataTransfer; 16 | 17 | public static async Task GetClipboardTextAsync() 18 | { 19 | DataPackageView dataPackage = Clipboard.GetContent(); 20 | return dataPackage.Contains(StandardDataFormats.Text) ? 21 | await dataPackage.GetTextAsync() : ""; 22 | } 23 | 24 | public static void SetClipboardText(string text) 25 | { 26 | var dataPackage = new DataPackage(); 27 | dataPackage.SetText(text); 28 | Clipboard.SetContent(dataPackage); 29 | } 30 | ``` 31 | 32 | ## See also 33 | 34 | [Clipboard class](https://msdn.microsoft.com/library/windows/apps/windows.applicationmodel.datatransfer.clipboard.aspx) 35 | [DataPackage class](https://msdn.microsoft.com/library/windows/apps/windows.applicationmodel.datatransfer.datapackage.aspx) 36 | [DataPackageView class](https://msdn.microsoft.com/library/windows/apps/windows.applicationmodel.datatransfer.datapackageview.aspx) 37 | [?: operator](https://msdn.microsoft.com/library/ty67wk28.aspx) 38 | 39 | For more advanced clipboard interactions, including handling non-text objects or firing events when the clipboard 40 | contents change, see [Copy and paste](https://msdn.microsoft.com/library/windows/apps/mt243291.aspx). 41 | 42 | -------------------------------------------------------------------------------- /tasks/Color-names-and-contrasting-foregrounds.md: -------------------------------------------------------------------------------- 1 | 5 | 6 | # Get the name and contrasting foreground of a color 7 | 8 | Provides extension methods for the Color structure. 9 | 10 | GetName gets the name of the color from the corresponding property of the Colors class, or null if there is no corresponding property. 11 | 12 | GetContrastingForegroundColor gets an appropriate foreground color (either black or white) to produce legible text when 13 | using the color as a background. (See screenshot below.) 14 | 15 | ```C# 16 | using System; 17 | using System.Collections.Generic; 18 | using System.Linq; 19 | using System.Reflection; 20 | using Windows.UI; 21 | 22 | public static class ColorExtensions 23 | { 24 | public static string GetName(this Color color) => 25 | ColorNameTuples 26 | .Where(c => c.Item1.Equals(color)) 27 | .Select(c => c.Item2).FirstOrDefault(); 28 | 29 | public static Color GetContrastingForegroundColor(this Color c) => 30 | c.R * 0.3 + c.G * 0.59 + c.B * 0.11 > 127 ? Colors.Black : Colors.White; 31 | 32 | private static List> ColorNameTuples => 33 | typeof(Colors).GetRuntimeProperties() 34 | .Select(p => Tuple.Create((Color)p.GetValue(null), p.Name)) 35 | .ToList(); 36 | } 37 | ``` 38 | 39 | ## Usage 40 | 41 | This example uses the GetName and GetContrastingForegroundColor extension methods to populate 42 | a collection of NamedColor data objects for display in a GridView. 43 | 44 | ```C# 45 | List NamedColors { get; } = 46 | (from property in typeof(Colors).GetRuntimeProperties() 47 | let color = (Color)property.GetValue(null) 48 | select new NamedColor 49 | { 50 | Brush = new SolidColorBrush(color), 51 | Name = color.GetName(), 52 | ForegroundBrush = new SolidColorBrush(color.GetContrastingForegroundColor()) 53 | }) 54 | .ToList(); 55 | ``` 56 | 57 | ![GridView showing color rectangles with the color name displayed on top in either black or white](Color-names-and-contrasting-foregrounds.png) 58 | 59 | ## See also 60 | 61 | [Color structure](https://msdn.microsoft.com/library/windows/apps/windows.ui.color.aspx) 62 | [Colors class](https://msdn.microsoft.com/library/windows/apps/windows.ui.colors.aspx) 63 | [GetRuntimeProperties extension method](https://msdn.microsoft.com/library/system.reflection.runtimereflectionextensions.getruntimeproperties.aspx) 64 | [Lambda expressions](https://msdn.microsoft.com/library/bb397687.aspx) (anonymous methods using the "=>" syntax) 65 | [Expression-bodied function members](http://blogs.msdn.com/b/csharpfaq/archive/2014/11/20/new-features-in-c-6.aspx) (methods and properties with the "=>" syntax) 66 | 67 | [Item containers and templates](https://docs.microsoft.com/windows/uwp/controls-and-patterns/listview-item-templates) uses similar code to demonstrate item template creation. 68 | -------------------------------------------------------------------------------- /tasks/Color-names-and-contrasting-foregrounds.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/Windows-task-snippets/4a5b507865787f27f13474f242827ca5a41ea527/tasks/Color-names-and-contrasting-foregrounds.png -------------------------------------------------------------------------------- /tasks/Colors-as-a-collection.md: -------------------------------------------------------------------------------- 1 | 5 | 6 | # Get all system colors as a collection 7 | 8 | Gets a collection containing all system colors supported in Universal Windows Platform (UWP) apps. 9 | 10 | ```C# 11 | using System.Collections.Generic; 12 | using System.Linq; 13 | using System.Reflection; 14 | using Windows.UI; 15 | 16 | public static IEnumerable GetAllColors() 17 | { 18 | return typeof(Colors).GetRuntimeProperties().Select(x => (Color)x.GetValue(null)); 19 | } 20 | ``` 21 | 22 | ## See also 23 | 24 | [Colors class](https://msdn.microsoft.com/library/windows/apps/windows.ui.colors.aspx) 25 | [Color structure](https://msdn.microsoft.com/library/windows/apps/windows.ui.color.aspx) 26 | [GetRuntimeProperties extension method](https://msdn.microsoft.com/library/system.reflection.runtimereflectionextensions.getruntimeproperties.aspx) 27 | [Lambda expressions](https://msdn.microsoft.com/library/bb397687.aspx) (anonymous methods using the "=>" syntax) 28 | -------------------------------------------------------------------------------- /tasks/Convert-DPI-rectangles.md: -------------------------------------------------------------------------------- 1 | 5 | 6 | # Convert the DPI of rectangles (C++) 7 | 8 | Converts a rectangle in a window from logical coordinates to physical coordinates or vice-versa, 9 | regardless of the dots per inch (DPI) awareness of the caller. 10 | 11 | Users can have multiple displays, each of which could have a different DPI setting. 12 | Modern apps might need to account for this and adjust the display based on DPI changes. 13 | The high-DPI APIs in the platform provide methods for converting points from one DPI to another. 14 | The methods below enhance this so you can convert entire rectangles when you are concerned with potential different DPI values. 15 | 16 | ```C++ 17 | BOOL GetLogicalRect(HWND relativeWindow, LPRECT rect) 18 | { 19 | if (rect == NULL) 20 | { 21 | return FALSE; 22 | } 23 | 24 | POINT topLeft, bottomRight; 25 | 26 | topLeft.x = rect->left; 27 | topLeft.y = rect->top; 28 | bottomRight.x = rect->right; 29 | bottomRight.y = rect->bottom; 30 | 31 | if (!PhysicalToLogicalPointForPerMonitorDPI(relativeWindow, &topLeft)) 32 | { 33 | return FALSE; 34 | } 35 | if (!PhysicalToLogicalPointForPerMonitorDPI(relativeWindow, &bottomRight)) 36 | { 37 | return FALSE; 38 | } 39 | 40 | rect->left = topLeft.x; 41 | rect->top = topLeft.y; 42 | rect->right = bottomRight.x; 43 | rect->bottom = bottomRight.y; 44 | 45 | return TRUE; 46 | } 47 | 48 | BOOL GetPhysicalRect(HWND relativeWindow, LPRECT rect) 49 | { 50 | if (rect == NULL) 51 | { 52 | return FALSE; 53 | } 54 | 55 | POINT topLeft, bottomRight; 56 | 57 | topLeft.x = rect->left; 58 | topLeft.y = rect->top; 59 | bottomRight.x = rect->right; 60 | bottomRight.y = rect->bottom; 61 | 62 | if (!LogicalToPhysicalPointForPerMonitorDPI(relativeWindow, &topLeft)) 63 | { 64 | return FALSE; 65 | } 66 | if (!LogicalToPhysicalPointForPerMonitorDPI(relativeWindow, &bottomRight)) 67 | { 68 | return FALSE; 69 | } 70 | 71 | rect->left = topLeft.x; 72 | rect->top = topLeft.y; 73 | rect->right = bottomRight.x; 74 | rect->bottom = bottomRight.y; 75 | 76 | return TRUE; 77 | } 78 | ``` 79 | 80 | ## See also 81 | 82 | [PhysicalToLogicalPointForPerMonitorDPI function](https://msdn.microsoft.com/library/windows/desktop/dn384112.aspx) 83 | [LogicalToPhysicalPointForPerMonitorDPI function](https://msdn.microsoft.com/library/windows/desktop/dn384110.aspx) 84 | 85 | For more info about how different DPI values work, see [High DPI](https://msdn.microsoft.com/library/windows/desktop/dd464646.aspx). 86 | -------------------------------------------------------------------------------- /tasks/Convert-RGB-to-HSV.md: -------------------------------------------------------------------------------- 1 | 5 | 6 | # Convert RGB to HSV 7 | 8 | Converts RGB (red, green, blue) color values to HSV (hue, saturation, value). 9 | Since Universal Windows Platform (UWP) system colors (contained in the Windows.UI.Colors class) 10 | only provide access to RGB values, this utility is useful for converting them if needed. 11 | 12 | ```C# 13 | using System; 14 | using System.Linq; 15 | 16 | public static Tuple RgbToHsv(double r, double g, double b) 17 | { 18 | double[] hsv = new double[3]; 19 | r = r / 255.0; 20 | g = g / 255.0; 21 | b = b / 255.0; 22 | double max = new[] { r, g, b }.Max(); 23 | double min = new[] { r, g, b }.Min(); 24 | double delta = max - min; 25 | hsv[1] = max != 0 ? delta / max : 0; 26 | hsv[2] = max; 27 | if (hsv[1] == 0) 28 | { 29 | return new Tuple(hsv[0], hsv[1], hsv[2]); 30 | } 31 | if (r == max) 32 | { 33 | hsv[0] = ((g - b) / delta); 34 | } 35 | else if (g == max) 36 | { 37 | hsv[0] = ((b - r) / delta) + 2.0; 38 | } 39 | else if (b == max) 40 | { 41 | hsv[0] = ((r - g) / delta) + 4.0; 42 | } 43 | hsv[0] *= 60.0; 44 | if (hsv[0] < 0) 45 | { 46 | hsv[0] += 360.0; 47 | } 48 | return new Tuple(hsv[0], hsv[1], hsv[2]); 49 | } 50 | ``` 51 | 52 | ## See also 53 | 54 | [Colors class](https://msdn.microsoft.com/library/windows/apps/windows.ui.colors.aspx) 55 | 56 | This C# task snippet is based on generic graphics algorithms from the text 57 | "Introduction to Computer Graphics" by Foley et al. ISBN # 0201609215. 58 | -------------------------------------------------------------------------------- /tasks/Convert-hex-to-color.md: -------------------------------------------------------------------------------- 1 | 5 | 6 | # Convert hex to color 7 | 8 | Converts a hexadecimal string representation of a color to its Windows.UI.Color ARGB (alpha, red, green, blue) equivalent or vice-versa. 9 | 10 | ```C# 11 | using System; 12 | using System.Globalization; 13 | using Windows.UI; 14 | 15 | public static Color ConvertHexToColor(string hex) 16 | { 17 | hex = hex.Remove(0, 1); 18 | byte a = hex.Length == 8 ? Byte.Parse(hex.Substring(0, 2), NumberStyles.HexNumber) : (byte)255; 19 | byte r = Byte.Parse(hex.Substring(hex.Length - 6, 2), NumberStyles.HexNumber); 20 | byte g = Byte.Parse(hex.Substring(hex.Length - 4, 2), NumberStyles.HexNumber); 21 | byte b = Byte.Parse(hex.Substring(hex.Length - 2), NumberStyles.HexNumber); 22 | return Color.FromArgb(a, r, g, b); 23 | } 24 | 25 | public static string ConvertColorToHex(Color color) 26 | { 27 | return $"#{color.A}{color.R}{color.G}{color.B}"; 28 | } 29 | ``` 30 | 31 | ## See also 32 | 33 | [Color sructure](https://msdn.microsoft.com/library/windows/apps/windows.ui.color.aspx) 34 | [ARGB](https://en.wikipedia.org/wiki/RGBA_color_space#ARGB_.28word-order.29) 35 | [Interpolated strings](https://msdn.microsoft.com/library/dn961160.aspx) (strings with a $ prefix) 36 | [?: operator](https://msdn.microsoft.com/library/ty67wk28.aspx) 37 | -------------------------------------------------------------------------------- /tasks/Data-binding-change-notification.md: -------------------------------------------------------------------------------- 1 | 5 | 6 | # Implement change notification 7 | 8 | Provides a simple, standard change-notification implementation. 9 | 10 | All one-way and two-way data bindings depend on change notification to refresh 11 | the data-bound controls. This typically involves a lot of boilerplate code that 12 | you can minimize by using this task snippet. 13 | 14 | To implement change notification for non-collection properties: 15 | 1. Either derive your class from this class, or use its contents to implement INotifyPropertyChanged on your class. (This 16 | is useful for classes that already derive from something else, such as Page.) 17 | 2. Implement your binding source properties using the pattern shown in the [Usage](#usage) section. 18 | 19 | ```C# 20 | using System; 21 | using System.ComponentModel; 22 | using System.Runtime.CompilerServices; 23 | 24 | public abstract class BindableBase : INotifyPropertyChanged 25 | { 26 | public event PropertyChangedEventHandler PropertyChanged; 27 | 28 | protected void OnPropertyChanged([CallerMemberName] string propertyName = null) 29 | { 30 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 31 | } 32 | 33 | protected bool SetProperty(ref T storage, T value, 34 | [CallerMemberName] String propertyName = null) 35 | { 36 | if (object.Equals(storage, value)) return false; 37 | storage = value; 38 | OnPropertyChanged(propertyName); 39 | return true; 40 | } 41 | } 42 | ``` 43 | 44 | The CallerMemberName attribute ensures that the propertyName parameter is set to the name 45 | of the calling property unless the caller passes a value explicitly. 46 | 47 | ## Usage 48 | 49 | ```C# 50 | public class TimestampInfo : BindableBase 51 | { 52 | private DateTimeOffset _timestamp; 53 | 54 | // Read/write property for which any changes must refresh the 55 | // UI controls bound to this property and to a dependent property. 56 | public DateTimeOffset Timestamp 57 | { 58 | get { return _timestamp; } 59 | set 60 | { 61 | // Update the backing field and raise PropertyChanged for this property. 62 | SetProperty(ref _timestamp, value); 63 | 64 | // Raise PropertyChanged for a read-only property that depends on this property. 65 | OnPropertyChanged(nameof(FormattedTimestamp)); 66 | } 67 | } 68 | 69 | // Read-only property that depends on another property 70 | // for both its value and for change notification. 71 | public string FormattedTimestamp 72 | { 73 | get 74 | { 75 | double minutesAgo = Timestamp == DateTimeOffset.MinValue ? 76 | 0 : Math.Floor((DateTimeOffset.Now - Timestamp).TotalMinutes); 77 | return $"{minutesAgo} minute{(minutesAgo == 1 ? "" : "s")} ago"; 78 | } 79 | } 80 | 81 | // Method that enables other code (such as a periodic timer) to raise PropertyChanged for FormattedTimestamp. 82 | public void RefreshFormattedTimestamp() => OnPropertyChanged(nameof(FormattedTimestamp)); 83 | } 84 | ``` 85 | 86 | The nameof operator lets you pass the name of a property without using a string constant. 87 | This helps avoid a common bug caused when you rename a property but fail to update its string representation. 88 | 89 | ## See also 90 | 91 | When binding to a collection property, use [ObservableCollection](https://msdn.microsoft.com/library/ms668604.aspx) 92 | as your property type, which provides a standard [INotifyCollectionChanged](https://msdn.microsoft.com/library/system.collections.specialized.inotifycollectionchanged.aspx) 93 | implementation. 94 | 95 | [Data binding](https://msdn.microsoft.com/library/windows/apps/mt210947.aspx) 96 | [INotifyPropertyChanged interface](https://msdn.microsoft.com/library/windows/apps/windows.ui.xaml.data.inotifypropertychanged.propertychanged.aspx) 97 | 98 | [CallerMemberNameAttribute class](https://msdn.microsoft.com/library/system.runtime.compilerservices.callermembernameattribute.aspx) 99 | [nameof expression](https://msdn.microsoft.com/library/dn986596.aspx) 100 | 101 | [Interpolated strings](https://msdn.microsoft.com/library/dn961160.aspx) (strings with a $ prefix) 102 | [Expression-bodied function members](http://blogs.msdn.com/b/csharpfaq/archive/2014/11/20/new-features-in-c-6.aspx) (methods and properties with the "=>" syntax) 103 | [?. operator](https://msdn.microsoft.com/library/dn986595.aspx) 104 | [?: operator](https://msdn.microsoft.com/library/ty67wk28.aspx) 105 | 106 | -------------------------------------------------------------------------------- /tasks/File-exists.md: -------------------------------------------------------------------------------- 1 |  5 | 6 | # Determine whether a file exists 7 | 8 | Determines whether a file exists in a given folder or a folder subtree. The file name should include the extension, but is not case-sensitive. 9 | 10 | ```C# 11 | using System; 12 | using System.Threading.Tasks; 13 | using Windows.Storage; 14 | using Windows.Storage.Search; 15 | 16 | public static async Task FileExistsInFolderAsync(StorageFolder folder, string filename) 17 | { 18 | var item = await folder.TryGetItemAsync(filename); 19 | return (item != null) && item.IsOfType(StorageItemTypes.File); 20 | } 21 | 22 | public static async Task FileExistsInSubtreeAsync(StorageFolder rootFolder, string filename) 23 | { 24 | if (filename.IndexOf('"') >= 0) throw new ArgumentException("filename"); 25 | var options = new QueryOptions 26 | { 27 | FolderDepth = FolderDepth.Deep, 28 | UserSearchFilter = $"filename:=\"{filename}\"" // “:=” is the exact-match operator 29 | }; 30 | var files = await rootFolder.CreateFileQueryWithOptions(options).GetFilesAsync(); 31 | return files.Count > 0; 32 | } 33 | 34 | public static async Task FileExistsAsync(StorageFolder folder, string filename, 35 | bool isRecursive = false) => isRecursive 36 | ? await FileExistsInSubtreeAsync(folder, filename) 37 | : await FileExistsInFolderAsync(folder, filename); 38 | ``` 39 | 40 | ## See also 41 | 42 | [StorageFolder class](https://msdn.microsoft.com/library/windows/apps/windows.storage.storagefolder.aspx) 43 | [StorageFile class](https://msdn.microsoft.com/library/windows/apps/windows.storage.storagefile.aspx) 44 | 45 | [?? operator](https://msdn.microsoft.com/library/ms173224.aspx) 46 | [?: operator](https://msdn.microsoft.com/library/ty67wk28.aspx) 47 | [Lambda expressions](https://msdn.microsoft.com/library/bb397687.aspx) (anonymous methods using the "=>" syntax) 48 | -------------------------------------------------------------------------------- /tasks/Folder-access-preservation.md: -------------------------------------------------------------------------------- 1 | 5 | 6 | # Preserve access to a StorageFolder 7 | 8 | Saves access permissions to a specific StorageFolder that a user has granted access to. 9 | 10 | By default, Universal Windows Platform (UWP) apps cannot access most of the file system - the user must manually "pick" folders before an app can use the files. 11 | If an app wants to access files in a particular folder repeatedly, it's a bad user experience to repeatedly ask the user for permission. 12 | This snippet shows how to persist permissions to a folder (even between suspend or shutdown) so an app only needs to ask the user to pick it once. 13 | 14 | The key parameter is an identifier (supplied by the developer) that specifies the folder to access. 15 | 16 | ```C# 17 | using System; 18 | using System.Threading.Tasks; 19 | using Windows.Storage; 20 | using Windows.Storage.AccessCache; 21 | using Windows.Storage.Pickers; 22 | 23 | public static async Task GetOrPickAndRememberFolderAsync(string key) 24 | { 25 | if (StorageApplicationPermissions.FutureAccessList.ContainsItem(key)) 26 | { 27 | return await StorageApplicationPermissions.FutureAccessList.GetFolderAsync(key); 28 | } 29 | var picker = new FolderPicker(); 30 | picker.FileTypeFilter.Add("*"); 31 | StorageFolder folder = await picker.PickSingleFolderAsync(); 32 | if (folder != null) 33 | { 34 | StorageApplicationPermissions.FutureAccessList.AddOrReplace(key, folder); 35 | } 36 | return folder; 37 | } 38 | ``` 39 | 40 | ## See also 41 | 42 | [Files, folders, and libraries](https://msdn.microsoft.com/library/windows/apps/mt185399.aspx) 43 | [StorageFolder class](https://msdn.microsoft.com/library/windows/apps/windows.storage.storagefolder.aspx) 44 | [StorageApplicationPermissions class](https://msdn.microsoft.com/library/windows/apps/windows.storage.accesscache.storageapplicationpermissions.aspx) 45 | [FolderPicker class](https://msdn.microsoft.com/library/windows/apps/windows.storage.pickers.folderpicker.aspx) 46 | -------------------------------------------------------------------------------- /tasks/InkCanvas-data-binding.md: -------------------------------------------------------------------------------- 1 | 5 | 6 | # Data-bind an InkCanvas control 7 | 8 | Enables you to use XAML data binding with ink stroke data in an InkCanvas control. 9 | 10 | The InkCanvas class does not expose a dependency property for its ink stroke data, so there is no built-in target for data binding. 11 | This snippet provides a InkStrokes attached property that you can use to bind to an InkStrokeContainer. This enables you to manipulate 12 | the ink stroke data programmatically (for example, to deserialize it from storage) and have the changes appear in the UI automatically. 13 | 14 | ```C# 15 | using Windows.UI.Input.Inking; 16 | using Windows.UI.Xaml; 17 | using Windows.UI.Xaml.Controls; 18 | 19 | public static class InkCanvasBinder 20 | { 21 | public static InkStrokeContainer GetInkStrokes(DependencyObject obj) => 22 | obj.GetValue(InkStrokesProperty) as InkStrokeContainer; 23 | 24 | public static void SetInkStrokes(DependencyObject obj, InkStrokeContainer value) => 25 | obj.SetValue(InkStrokesProperty, value); 26 | 27 | public static DependencyProperty InkStrokesProperty = DependencyProperty.RegisterAttached( 28 | "InkStrokes", typeof(InkStrokeContainer), typeof(InkCanvasBinder), 29 | new PropertyMetadata(null, InkStrokesProperty_PropertyChanged)); 30 | 31 | private static void InkStrokesProperty_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 32 | { 33 | var inkCanvas = d as InkCanvas; 34 | if (inkCanvas != null) inkCanvas.InkPresenter.StrokeContainer = e.NewValue as InkStrokeContainer; 35 | } 36 | } 37 | ``` 38 | 39 | ## Usage 40 | 41 | In this example, the InkCanvas is bound to a read-only MyInkStrokeContainer property of type InkStrokeContainer defined in the page's code-behind file. 42 | 43 | ```xaml 44 | 45 | ``` 46 | 47 | ## See also 48 | 49 | [InkCanvas class](https://msdn.microsoft.com/library/windows/apps/windows.ui.xaml.controls.inkcanvas.aspx) 50 | [InkStrokeContainer class](https://msdn.microsoft.com/library/windows/apps/windows.ui.input.inking.inkstrokecontainer.aspx) 51 | 52 | [Dependency properties overview](https://msdn.microsoft.com/windows/uwp/xaml-platform/dependency-properties-overview) 53 | [Expression-bodied function members](http://blogs.msdn.com/b/csharpfaq/archive/2014/11/20/new-features-in-c-6.aspx) (methods and properties with the "=>" syntax) 54 | [x:Bind markup extension](https://msdn.microsoft.com/windows/uwp/xaml-platform/x-bind-markup-extension) 55 | -------------------------------------------------------------------------------- /tasks/Launch-executable.md: -------------------------------------------------------------------------------- 1 | 5 | 6 | # Launch executable 7 | 8 | Launches the default app or other executable (.exe or .bat file) associated with the specified filename extension. 9 | 10 | The exeId parameter specifies the extension. You must also have configured the association 11 | between the custom file type and the target executable, either manually or through Group Policy. 12 | If the association is not set when LaunchExeAsync is run, the system will prompt the user to select 13 | any program of their choice. 14 | 15 | The prompt parameter specifies whether to warn the user that the current app is trying to switch apps 16 | or whether to proceed silently. 17 | 18 | ```C# 19 | using System; 20 | using System.IO; 21 | using System.Threading.Tasks; 22 | using Windows.Storage; 23 | using Windows.System; 24 | 25 | public static async Task LaunchExeAsync(string exeId, bool prompt = true) 26 | { 27 | exeId = "." + exeId; 28 | StorageFile file = null; 29 | try 30 | { 31 | file = await ApplicationData.Current.LocalFolder.GetFileAsync(exeId); 32 | } 33 | catch (FileNotFoundException) 34 | { 35 | file = await ApplicationData.Current.LocalFolder.CreateFileAsync(exeId); 36 | } 37 | await Launcher.LaunchFileAsync(file, new LauncherOptions { TreatAsUntrusted = prompt }); 38 | } 39 | ``` 40 | 41 | This method is primarily useful when you can configure the file type association 42 | ahead of time, for example with internal testing or with line-of-business (LOB) apps where 43 | you have some control over your users' systems. It works by first creating a blank file with the specified custom extension, 44 | then using the Launcher class to "open" the file using the associated executable. Although the 45 | file is blank, so there is nothing to actually open, the executable is launched anyway. 46 | 47 | ## See also 48 | 49 | [Launcher class](https://msdn.microsoft.com/library/windows/apps/windows.system.launcher) 50 | [Launcher.LaunchFileAsync method](https://msdn.microsoft.com/library/windows/apps/hh701465.aspx) 51 | -------------------------------------------------------------------------------- /tasks/Location-of-device.md: -------------------------------------------------------------------------------- 1 | 5 | 6 | # Get a device's current location 7 | 8 | Gets the device's current location (represented as longitude and latitude), if the user allows it. 9 | 10 | **Note:** To use this method, you must enable the Location capability in the Package.appxmanifest file of your app. 11 | 12 | ```C# 13 | using System; 14 | using System.Threading.Tasks; 15 | using Windows.Devices.Geolocation; 16 | 17 | public static async Task> GetCurrentCoordinatesAsync() 18 | { 19 | if (await Geolocator.RequestAccessAsync() == GeolocationAccessStatus.Allowed) 20 | { 21 | var geoposition = await new Geolocator().GetGeopositionAsync(); 22 | var position = geoposition.Coordinate.Point.Position; 23 | return new Tuple(position.Longitude, position.Latitude); 24 | } 25 | return null; 26 | } 27 | ``` 28 | 29 | ## See also 30 | 31 | [Geolocator class](https://msdn.microsoft.com/library/windows/apps/windows.devices.geolocation.geolocator.aspx) 32 | [Geolocator.GetGeopositionAsync](https://msdn.microsoft.com/library/windows/apps/xaml/hh973536) 33 | -------------------------------------------------------------------------------- /tasks/Media-file-concatenation.md: -------------------------------------------------------------------------------- 1 | 5 | 6 | # Concatenate media files 7 | 8 | Concatenate two or more media files and save the result to a file using the specified preferences. 9 | 10 | This method defaults to encoding MP3 files, but works with media files in a variety of formats, including video files. 11 | 12 | ```C# 13 | using System; 14 | using System.Collections.Generic; 15 | using System.Diagnostics; 16 | using System.Linq; 17 | using System.Threading.Tasks; 18 | using Windows.ApplicationModel.Core; 19 | using Windows.Media.Editing; 20 | using Windows.Media.MediaProperties; 21 | using Windows.Storage; 22 | using Windows.UI.Core; 23 | 24 | public static class Helpers 25 | { 26 | public static async Task ConcatenateMediaFilesAsync(this IEnumerable inputFiles, 27 | StorageFile outputFile, MediaEncodingProfile encodingProfile = null, 28 | MediaTrimmingPreference trimmingPreference = MediaTrimmingPreference.Fast) 29 | { 30 | encodingProfile = encodingProfile ?? MediaEncodingProfile.CreateMp3(AudioEncodingQuality.High); 31 | var composition = new MediaComposition(); 32 | try 33 | { 34 | inputFiles.ToList().ForEach(async file => 35 | composition.Clips.Add(await MediaClip.CreateFromFileAsync(file))); 36 | 37 | var transcodeOperation = composition.RenderToFileAsync( 38 | outputFile, trimmingPreference, encodingProfile); 39 | 40 | transcodeOperation.Progress = async (transcodeResult, progress) => 41 | await CoreApplication.MainView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, 42 | () => { Debug.WriteLine($"Transcode progress: {progress}"); }); 43 | 44 | var result = await transcodeOperation; 45 | Debug.WriteLine($"Transcode result: {result.ToString()}"); 46 | } 47 | catch (Exception e) 48 | { 49 | Debug.WriteLine($"Exception during transcoding: {e.Message}"); 50 | } 51 | } 52 | } 53 | ``` 54 | 55 | ## Usage 56 | 57 | The following usage snippet shows how to concatenate MP3 files selected by the user. (Note that ConcatenateMediaFilesAsync 58 | 59 | ```C# 60 | using System; 61 | using System.Diagnostics; 62 | using Windows.Storage; 63 | using Windows.Storage.Pickers; 64 | using Windows.UI.Xaml; 65 | 66 | private async void Button_Click(object sender, RoutedEventArgs e) 67 | { 68 | var picker = new FileOpenPicker() { SuggestedStartLocation = PickerLocationId.MusicLibrary }; 69 | picker.FileTypeFilter.Add(".mp3"); 70 | 71 | var pickedFiles = await picker.PickMultipleFilesAsync(); 72 | if (pickedFiles == null) { Debug.WriteLine("File picking cancelled"); return; } 73 | 74 | var outputFile = await ApplicationData.Current.LocalFolder.CreateFileAsync( 75 | "test.mp3", CreationCollisionOption.ReplaceExisting); 76 | 77 | await pickedFiles.ConcatenateMediaFilesAsync(outputFile); 78 | } 79 | ``` 80 | 81 | ## See also 82 | 83 | [MediaComposition class](https://msdn.microsoft.com/library/windows/apps/windows.media.editing.mediacomposition.aspx) 84 | [MediaClip class](https://msdn.microsoft.com/library/windows/apps/windows.media.editing.mediaclip.aspx) 85 | [MediaEncodingProfile](https://msdn.microsoft.com/library/windows/apps/windows.media.mediaproperties.mediaencodingprofile.aspx) 86 | 87 | [?? operator](https://msdn.microsoft.com/library/ms173224.aspx) 88 | [Lambda expressions](https://msdn.microsoft.com/library/bb397687.aspx) (anonymous methods using the "=>" syntax) 89 | [Extension methods](https://msdn.microsoft.com/en-us/library/bb383977.aspx) 90 | [Interpolated strings](https://msdn.microsoft.com/library/dn961160.aspx) (strings with a $ prefix) 91 | -------------------------------------------------------------------------------- /tasks/Play-sound-once-or-looped.md: -------------------------------------------------------------------------------- 1 | 5 | 6 | # Play a sound once or looped 7 | 8 | Plays a sound, either once or continuously. 9 | 10 | ```C# 11 | using System; 12 | using System.Threading.Tasks; 13 | using Windows.Storage; 14 | using Windows.UI.Xaml.Controls; 15 | 16 | public static async Task PlayAudioAsync(IStorageFile mediaFile, bool looping = false) 17 | { 18 | var stream = await mediaFile.OpenAsync(FileAccessMode.Read).AsTask(); 19 | var mediaControl = new MediaElement() { IsLooping = looping }; 20 | mediaControl.SetSource(stream, mediaFile.ContentType); 21 | mediaControl.Play(); 22 | } 23 | ``` 24 | 25 | The sound is passed in as an IStorageFile. You can load your sound file as a 26 | StorageFile object by using a method like GetFileFromApplicationUriAsync. 27 | 28 | There are several ways to play sound in a Universal Windows Platform (UWP) app. This method 29 | uses the MediaElement class. The AudioGraph class provides additional control over playing sound. 30 | 31 | ## Usage 32 | 33 | ```C# 34 | var soundFile = await StorageFile.GetFileFromApplicationUriAsync( 35 | new Uri("ms-appx:///Assets/test.mp3")); 36 | await PlayAudioAsync(soundFile); 37 | ``` 38 | 39 | ## See also 40 | 41 | [IStorageFile interface](https://msdn.microsoft.com/library/windows/apps/windows.storage.istoragefile.aspx) 42 | [StorageFile class](https://msdn.microsoft.com/library/windows/apps/windows.storage.storagefile.aspx) 43 | [StorageFile.GetFileFromApplicationUriAsync method](https://msdn.microsoft.com/library/windows/apps/windows.storage.storagefile.getfilefromapplicationuriasync.aspx) 44 | [MediaElement class](https://msdn.microsoft.com/library/windows/apps/windows.ui.xaml.controls.mediaelement.aspx) 45 | [AudioGraph class](https://msdn.microsoft.com/library/windows/apps/windows.media.audio.audiograph.aspx) 46 | 47 | -------------------------------------------------------------------------------- /tasks/Show-dialog-box.md: -------------------------------------------------------------------------------- 1 | 5 | 6 | # Show a dialog box 7 | 8 | These methods provide convenient ways to show a dialog box, 9 | and can be called from the UI thread or from a background thread: 10 | 11 | * [Simple dialog](#simple-dialog) 12 | * [Action dialog](#action-dialog) 13 | 14 | ## Simple dialog 15 | 16 | Shows a simple dialog box displaying a message, an optional title, 17 | and a "Close" button for the user to dismiss it. 18 | 19 | ```C# 20 | using System; 21 | using System.Threading.Tasks; 22 | using Windows.ApplicationModel.Core; 23 | using Windows.UI.Core; 24 | using Windows.UI.Popups; 25 | 26 | public static async Task ShowDialogAsync(string contents, string title = null) 27 | { 28 | var dialog = title == null ? 29 | new MessageDialog(contents) { CancelCommandIndex = 0 } : 30 | new MessageDialog(contents, title) { CancelCommandIndex = 0 }; 31 | await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync( 32 | CoreDispatcherPriority.Normal, async () => await dialog.ShowAsync()); 33 | } 34 | ``` 35 | 36 | ## Action dialog 37 | 38 | Shows a dialog box with a message, an optional title, and two buttons for "OK" and 39 | "Cancel". 40 | 41 | This method takes a callback action that is invoked when the user presses OK. You 42 | can also provide your own strings for the title and the two buttons. 43 | 44 | ```C# 45 | using System; 46 | using System.Threading.Tasks; 47 | using Windows.ApplicationModel.Core; 48 | using Windows.UI.Core; 49 | using Windows.UI.Popups; 50 | 51 | public static async Task ShowActionDialogAsync(string contents, Action callback, 52 | string title = null, string okButtonText = "OK", string cancelButtonText = "Cancel") 53 | { 54 | var dialog = title == null ? 55 | new MessageDialog(contents) { CancelCommandIndex = 1 } : 56 | new MessageDialog(contents, title) { CancelCommandIndex = 1 }; 57 | dialog.Commands.Add(new UICommand(okButtonText, command => callback())); 58 | dialog.Commands.Add(new UICommand(cancelButtonText)); 59 | await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync( 60 | CoreDispatcherPriority.Normal, async () => await dialog.ShowAsync()); 61 | } 62 | ``` 63 | 64 | ### Usage 65 | 66 | ```C# 67 | await ShowActionDialogAsync("Do you really want to delete all items?", 68 | () => { /* delete all items */ }, "Warning"); 69 | ``` 70 | 71 | ## See also 72 | 73 | [MessageDialog class](https://msdn.microsoft.com/library/windows/apps/br208674) 74 | [UICommand class](https://msdn.microsoft.com/library/windows/apps/windows.ui.popups.uicommand.aspx) 75 | [CoreDispatcher.RunAsync method](https://msdn.microsoft.com/library/windows/apps/windows.ui.core.coredispatcher.runasync.aspx) 76 | [Lambda expressions](https://msdn.microsoft.com/library/bb397687.aspx) (anonymous methods using the "=>" syntax) 77 | [?: operator](https://msdn.microsoft.com/library/ty67wk28.aspx) 78 | -------------------------------------------------------------------------------- /tasks/Socket-programming-with-TCP.md: -------------------------------------------------------------------------------- 1 | 5 | 6 | # Sending and receiving a message over TCP 7 | 8 | These methods provide simple string-based communication over a TCP socket connection: 9 | 10 | * [Sending a message](#sending-a-message) 11 | * [Receiving a message](#receiving-a-message) 12 | 13 | ## Sending a message 14 | 15 | The remoteHost and remotePort parameter values must match the device that is 16 | listening for incoming connections and will be receiving the message. 17 | 18 | ```C# 19 | using System; 20 | using System.IO; 21 | using System.Threading.Tasks; 22 | using Windows.Networking; 23 | using Windows.Networking.Sockets; 24 | 25 | public static async Task SendStringTcpAsync(HostName remoteHost, 26 | string remotePort, string message) 27 | { 28 | using (var socket = new StreamSocket()) 29 | { 30 | await socket.ConnectAsync(remoteHost, remotePort); 31 | using (var writer = new StreamWriter( 32 | socket.OutputStream.AsStreamForWrite())) 33 | { 34 | await writer.WriteLineAsync(message); 35 | await writer.FlushAsync(); 36 | } 37 | } 38 | } 39 | ``` 40 | 41 | ### Usage 42 | 43 | ```C# 44 | try 45 | { 46 | await SendStringTcpAsync(new HostName("192.168.0.5"), 47 | "56789", "Hello, world!"); 48 | } 49 | catch (Exception) 50 | { 51 | // Handle relevant errors. 52 | } 53 | ``` 54 | 55 | ## Receiving a message 56 | 57 | The specified callback is called every time a message is received. 58 | 59 | The return value is a cleanup action that you should call when you are finished receiving messages. 60 | 61 | ```C# 62 | using System; 63 | using System.IO; 64 | using System.Threading.Tasks; 65 | using Windows.Foundation; 66 | using Windows.Networking.Sockets; 67 | 68 | public static async Task ReceiveStringTcpAsync(string port, 69 | Action callback) 70 | { 71 | var socket = new StreamSocketListener(); 72 | TypedEventHandler handler = 74 | async (sender, args) => 75 | { 76 | using (var reader = new StreamReader( 77 | args.Socket.InputStream.AsStreamForRead())) 78 | { 79 | string message = await reader.ReadLineAsync(); 80 | callback(message, args.Socket.Information); 81 | } 82 | }; 83 | 84 | socket.ConnectionReceived += handler; 85 | await socket.BindServiceNameAsync(port); 86 | 87 | Action cleanup = () => 88 | { 89 | socket.ConnectionReceived -= handler; 90 | socket.Dispose(); 91 | }; 92 | return cleanup; 93 | } 94 | ``` 95 | 96 | ### Usage 97 | 98 | You can bind to any port that is not already being 99 | used by the device. If the port is already in use, the ReceiveStringTcpAsync 100 | method will throw an exception. 101 | 102 | ```C# 103 | Action cleanup = null; 104 | try 105 | { 106 | cleanup = await ReceiveStringTcpAsync("56789", (message, information) => 107 | { 108 | System.Diagnostics.Debug.WriteLine( 109 | $"\"{message}\" was received from {information.RemoteAddress}."); 110 | }); 111 | } 112 | catch (Exception) 113 | { 114 | // Handle relevant errors. 115 | } 116 | 117 | // Clean up resources at the appropriate place in your code. 118 | if (cleanup != null) cleanup(); 119 | ``` 120 | 121 | ## See also 122 | 123 | [StreamSocket class](https://msdn.microsoft.com/library/windows/apps/windows.networking.sockets.streamsocket.aspx) 124 | [StreamSocketListener class](https://msdn.microsoft.com/library/windows/apps/windows.networking.sockets.streamsocketlistener.aspx) 125 | [Exceptions in Windows.Networking.Sockets](https://msdn.microsoft.com/library/windows/apps/mt280234.aspx#Exceptions_in_Windows.Networking.Sockets) 126 | 127 | [Lambda expressions](https://msdn.microsoft.com/library/bb397687.aspx) (anonymous methods using the "=>" syntax) 128 | [Interpolated strings](https://msdn.microsoft.com/library/dn961160.aspx) (strings with a $ prefix) 129 | 130 | For code that handles more complex TCP socket communication scenarios, see the 131 | [P2PHelper](https://github.com/Microsoft/Windows-appsample-quizgame/tree/master/P2PHelper) project in the 132 | [QuizGame sample](https://github.com/Microsoft/Windows-appsample-quizgame). -------------------------------------------------------------------------------- /tasks/Socket-programming-with-UDP.md: -------------------------------------------------------------------------------- 1 | 5 | 6 | # Sending and receiving a message over UDP 7 | 8 | These methods provide simple string-based communication over a UDP socket connection: 9 | 10 | * [Sending a message](#sending-a-message) 11 | * [Receiving a message](#receiving-a-message) 12 | 13 | ## Sending a message 14 | 15 | The remoteHost and remotePort parameter values must match the device that is listening 16 | for incoming connections and will be receiving the message. 17 | 18 | ```C# 19 | using System; 20 | using System.IO; 21 | using System.Threading.Tasks; 22 | using Windows.Networking; 23 | using Windows.Networking.Sockets; 24 | 25 | public static async Task SendStringUdpAsync(HostName remoteHost, 26 | string remotePort, string message) 27 | { 28 | using (var socket = new DatagramSocket()) 29 | { 30 | var stream = (await socket.GetOutputStreamAsync( 31 | remoteHost, remotePort)).AsStreamForWrite(); 32 | using (var writer = new StreamWriter(stream)) 33 | { 34 | await writer.WriteLineAsync(message); 35 | await writer.FlushAsync(); 36 | } 37 | } 38 | } 39 | ``` 40 | 41 | ### Usage 42 | 43 | ```C# 44 | try 45 | { 46 | await SendStringUdpAsync(new HostName("192.168.0.5"), 47 | "56789", "Hello, world!"); 48 | } 49 | catch (Exception) 50 | { 51 | // Handle appropriate errors. 52 | } 53 | ``` 54 | 55 | ## Receiving a message 56 | 57 | The specified callback is called everytime a message is received. 58 | 59 | The return value is a cleanup action that you should call when you are finished receiving messages. 60 | 61 | ```C# 62 | using System; 63 | using System.IO; 64 | using System.Threading.Tasks; 65 | using Windows.Foundation; 66 | using Windows.Networking.Sockets; 67 | 68 | public static async Task ReceiveStringUdpAsync(string port, 69 | Action callback) 70 | { 71 | var socket = new DatagramSocket(); 72 | TypedEventHandler handler = 74 | async (sender, args) => 75 | { 76 | using (var reader = new StreamReader( 77 | args.GetDataStream().AsStreamForRead())) 78 | { 79 | string message = await reader.ReadLineAsync(); 80 | callback(message, args); 81 | } 82 | }; 83 | 84 | socket.MessageReceived += handler; 85 | await socket.BindServiceNameAsync(port); 86 | 87 | Action cleanup = () => 88 | { 89 | socket.MessageReceived -= handler; 90 | socket.Dispose(); 91 | }; 92 | return cleanup; 93 | } 94 | ``` 95 | 96 | ### Usage 97 | 98 | You can bind to any port that is not already being used by the device. 99 | If the port is already in use, the ReceiveStringUdpAsync method will throw an exception. 100 | 101 | ```C# 102 | Action cleanup = null; 103 | try 104 | { 105 | cleanup = await ReceiveStringUdpAsync("56789", (message, args) => 106 | { 107 | System.Diagnostics.Debug.WriteLine( 108 | $"\"{message}\" was received from {args.RemoteAddress}."); 109 | }); 110 | } 111 | catch (Exception) 112 | { 113 | // Handle appropriate errors. 114 | } 115 | 116 | // Clean up resources at the appropriate place in your code. 117 | if (cleanup != null) cleanup(); 118 | ``` 119 | 120 | ## See also 121 | 122 | [DatagramSocket class](https://msdn.microsoft.com/library/windows/apps/windows.networking.sockets.datagramsocket.aspx) 123 | [Exceptions in Windows.Networking.Sockets](https://msdn.microsoft.com/library/windows/apps/mt280234.aspx#Exceptions_in_Windows.Networking.Sockets) 124 | 125 | [Lambda expressions](https://msdn.microsoft.com/library/bb397687.aspx) (anonymous methods using the "=>" syntax) 126 | [Interpolated strings](https://msdn.microsoft.com/library/dn961160.aspx) (strings with a $ prefix) 127 | 128 | For code that handles more complex UDP socket communication scenarios, see the 129 | [P2PHelper](https://github.com/Microsoft/Windows-appsample-quizgame/tree/master/P2PHelper) project in the 130 | [QuizGame sample](https://github.com/Microsoft/Windows-appsample-quizgame). 131 | -------------------------------------------------------------------------------- /tasks/Store-app-rating-pop-up.md: -------------------------------------------------------------------------------- 1 | 5 | 6 | # Show a pop-up asking the user to rate the app on its Store page 7 | 8 | Displays a pop-up message that asks the user to rate the app. If the user agrees, 9 | they are redirected to the app's store page to indicate their rating. 10 | 11 | ```C# 12 | using System; 13 | using System.Threading.Tasks; 14 | using Windows.ApplicationModel; 15 | using Windows.System; 16 | using Windows.UI.Popups; 17 | 18 | public static async Task ShowStoreRatingDialogAsync(string message, 19 | string okButtonText = "OK", string cancelButtonText = "Cancel") 20 | { 21 | Action handler = async () => await Launcher.LaunchUriAsync(new Uri( 22 | $"ms-windows-store:REVIEW?PFN={Package.Current.Id.FamilyName}")); 23 | var messageDialog = new MessageDialog(message) { CancelCommandIndex = 1 }; 24 | messageDialog.Commands.Add(new UICommand(okButtonText, command => handler())); 25 | messageDialog.Commands.Add(new UICommand(cancelButtonText)); 26 | await messageDialog.ShowAsync(); 27 | } 28 | ``` 29 | 30 | ## See also 31 | 32 | [MessageDialog class](https://msdn.microsoft.com/library/windows/apps/xaml/windows.ui.popups.messagedialog.aspx) 33 | [UICommand class](https://msdn.microsoft.com/library/windows/apps/windows.ui.popups.uicommand.aspx) 34 | [Launcher class](https://msdn.microsoft.com/library/windows/apps/windows.system.launcher) 35 | [Launcher.LaunchUriAsync methods](https://msdn.microsoft.com/library/windows/apps/windows.system.launcher.launchuriasync.aspx) 36 | [Interpolated strings](https://msdn.microsoft.com/library/dn961160.aspx) (strings with a $ prefix) 37 | -------------------------------------------------------------------------------- /tasks/Thread-switching-within-a-task.md: -------------------------------------------------------------------------------- 1 | 5 | 6 | # Thread switching within a task 7 | 8 | Enables code running in a task to continue 9 | on another thread. 10 | 11 | Code running on a background thread cannot manipulate UI elements directly 12 | without raising a cross-thread exception. 13 | Other task snippets accomplish this by 14 | putting the desired code inside a lambda which you schedule to run on the UI thread 15 | ([snippet 1](UI-thread-access-from-background-thread.md), 16 | [snippet 2](UI-thread-task-await-from-background-thread.md)). 17 | 18 | This task snippet provides 19 | an alternate coding pattern which encodes the thread switches 20 | in the flow of the function. 21 | 22 | ```C# 23 | using System; 24 | using System.Runtime.CompilerServices; 25 | using System.Threading; 26 | using Windows.System; 27 | using Windows.System.Threading; 28 | using Windows.UI.Core; 29 | 30 | struct DispatcherThreadSwitcher : INotifyCompletion 31 | { 32 | internal DispatcherThreadSwitcher(CoreDispatcher dispatcher) => 33 | this.dispatcher = dispatcher; 34 | public DispatcherThreadSwitcher GetAwaiter() => this; 35 | public bool IsCompleted => dispatcher.HasThreadAccess; 36 | public void GetResult() { } 37 | public void OnCompleted(Action continuation) => 38 | _ = dispatcher.RunAsync(CoreDispatcherPriority.Normal, 39 | () => continuation()); 40 | CoreDispatcher dispatcher; 41 | } 42 | 43 | struct DispatcherQueueThreadSwitcher : INotifyCompletion 44 | { 45 | internal DispatcherQueueThreadSwitcher(DispatcherQueue dispatcher) => 46 | this.dispatcher = dispatcher; 47 | public DispatcherQueueThreadSwitcher GetAwaiter() => this; 48 | public bool IsCompleted => dispatcher.HasThreadAccess; 49 | public bool GetResult() => dispatcher.HasThreadAccess; 50 | public void OnCompleted(Action continuation) { 51 | if (!dispatcher.TryEnqueue(() => continuation())) 52 | continuation(); 53 | } 54 | DispatcherQueue dispatcher; 55 | } 56 | 57 | struct ThreadPoolThreadSwitcher : INotifyCompletion 58 | { 59 | public ThreadPoolThreadSwitcher GetAwaiter() => this; 60 | public bool IsCompleted => 61 | SynchronizationContext.Current == null; 62 | public void GetResult() { } 63 | public void OnCompleted(Action continuation) => 64 | _ = ThreadPool.RunAsync(_ => continuation()); 65 | } 66 | 67 | class ThreadSwitcher 68 | { 69 | static public DispatcherThreadSwitcher ResumeForegroundAsync( 70 | CoreDispatcher dispatcher) => 71 | new DispatcherThreadSwitcher(dispatcher); 72 | static public DispatcherQueueThreadSwitcher ResumeForegroundAsync( 73 | DispatcherQueue dispatcher) => 74 | new DispatcherQueueThreadSwitcher(dispatcher); 75 | static public ThreadPoolThreadSwitcher ResumeBackgroundAsync() => 76 | new ThreadPoolThreadSwitcher(); 77 | } 78 | ``` 79 | 80 | ## Usage 81 | 82 | You can `await` the `ResumeForegroundAsync()` or 83 | `ResumeBackgroundAsync()` methods 84 | to switch the context of the task to a 85 | foreground thread or background thread, 86 | respectively. 87 | 88 | The result of `await ThreadSwitcher.ResumeForegroundAsync(DispatcherQueue)` is a `bool` 89 | that represents whether the thread switch was successful. 90 | The other `ThreadSwitcher` methods do not provide a result. 91 | 92 | ```C# 93 | private async Task OnStatusChanged() 94 | { 95 | // Switch to the UI thread to interact with UI elements 96 | await ThreadSwitcher.ResumeForegroundAsync(this.Dispatcher); 97 | 98 | var isEnabled = EnabledCheckBox.IsChecked.Value; 99 | var message = MessageTextBlock.Text; 100 | 101 | // Go back to background thread for expensive processing 102 | await ThreadSwitcher.ResumeBackgroundAsync(); 103 | 104 | var result = DoExpensiveProcessing(isEnabled, message); 105 | 106 | // Switch to the UI thread to update with results 107 | await ThreadSwitcher.ResumeForegroundAsync(this.Dispatcher); 108 | 109 | ResultTextBlock.Text = result; 110 | } 111 | 112 | ``` 113 | 114 | This pattern makes it easier to share variables between 115 | the different parts of a task. 116 | The version with explicit lambdas would look like this: 117 | 118 | ```C# 119 | private async Task OnStatusChanged() 120 | { 121 | bool isEnabled = false; 122 | string message = null; 123 | 124 | // Switch to the UI thread to interact with UI elements 125 | await Dispatcher.RunAsync(() => 126 | { 127 | isEnabled = EnabledCheckBox.IsChecked.Value; 128 | message = MessageTextBlock.Text; 129 | }); 130 | 131 | // Back on the background thread 132 | var result = DoExpensiveProcessing(isEnabled, message); 133 | 134 | // Switch to the UI thread to update with results 135 | await Dispatcher.RunAsync(() => 136 | { 137 | ResultTextBlock.Text = result; 138 | }); 139 | } 140 | ``` 141 | 142 | Note that we had to predeclare and preinitialize 143 | the `isEnabled` and 144 | `message` variables so that they can be shared between 145 | the main function and the lambda. 146 | This can be problematic if the shared variables are of 147 | an anonymous type. 148 | 149 | This pattern is particularly useful when the thread switching is 150 | conditional: 151 | 152 | ```C# 153 | private async Task OnStatusChanged() 154 | { 155 | if (requiresUI) 156 | { 157 | await ThreadSwitcher.ResumeForegroundAsync(this.Dispatcher); 158 | } 159 | 160 | /* task is on UI thread if requiresUI is true */ 161 | } 162 | 163 | ``` 164 | 165 | or if the thread switch is part of a 166 | more complex control flow: 167 | 168 | ```C# 169 | private async Task OnStatusChanged() 170 | { 171 | int total = 0; 172 | for (var view in viewsToUpdate) 173 | { 174 | // Switch to each view's thread in order to call GetItemCount(). 175 | await ThreadSwitcher.ResumeForegroundAsync(view.Dispatcher); 176 | total += view.GetItemCount(); 177 | } 178 | 179 | // Return to background thread to finish up 180 | await ThreadSwitcher.ResumeBackgroundAsync(); 181 | 182 | /* do something with the total */ 183 | } 184 | ``` 185 | 186 | The lambda-based version of the above loop would be 187 | 188 | ```C# 189 | private async Task OnStatusChanged() 190 | { 191 | int total = 0; 192 | for (var view in viewsToUpdate) 193 | { 194 | // Switch to each view's thread in order to call GetItemCount(). 195 | await view.Dispatcher.RunAsync(() => 196 | { 197 | total += view.GetItemCount(); 198 | }); 199 | } 200 | 201 | /* do something with the total */ 202 | } 203 | ``` 204 | 205 | The lambda-based version returns to the original thread 206 | after interrogating each view, 207 | resulting in twice as many thread switches as the 208 | `ThreadSwitcher`-based version. 209 | 210 | ## See also 211 | 212 | [CoreDispatcher.RunAsync method](https://docs.microsoft.com/uwp/api/Windows.UI.Core.CoreDispatcher.RunAsync) 213 | [ThreadPool.RunAsync method](https://docs.microsoft.com/uwp/api/Windows.System.Threading.ThreadPool.RunAsync) 214 | 215 | [Lambda expressions](https://msdn.microsoft.com/library/bb397687.aspx) (anonymous methods using the "=>" syntax) 216 | -------------------------------------------------------------------------------- /tasks/Time-specific-salutation.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | # Time-specific salutation 6 | 7 | Generates a simple greeting based on the time of day. 8 | 9 | ```C# 10 | public static string Salutation() 11 | { 12 | var now = System.DateTime.Now; 13 | return 14 | now.Hour < 12 ? "Good morning" : 15 | now.Hour < 18 ? "Good afternoon" : 16 | now.Hour < 21 ? "Good evening" : 17 | /* otherwise */ "Good night"; 18 | } 19 | ``` 20 | 21 | ## Usage 22 | 23 | ```C# 24 | System.Diagnostics.Debug.WriteLine(Salutation()); 25 | ``` 26 | 27 | ## See also 28 | 29 | [DateTime](https://msdn.microsoft.com/library/windows/apps/windows.foundation.datetime.aspx) 30 | [?: operator](https://msdn.microsoft.com/library/ty67wk28.aspx) -------------------------------------------------------------------------------- /tasks/UI-thread-access-from-background-thread.md: -------------------------------------------------------------------------------- 1 | 5 | 6 | # Update the UI thread from a background thread 7 | 8 | Enables code running on a background thread to schedule work that will run on the UI thread. 9 | 10 | Code running on a background thread cannot manipulate UI elements directly without raising 11 | a cross-thread exception. Instead, you must run UI code using a dispatcher. This task snippet 12 | encapsulates the typical dispatcher usage in Universal Windows Platform (UWP) apps. 13 | 14 | ```C# 15 | using System; 16 | using System.Threading.Tasks; 17 | using Windows.ApplicationModel.Core; 18 | using Windows.UI.Core; 19 | 20 | public static async Task CallOnUiThreadAsync(CoreDispatcher dispatcher, DispatchedHandler handler) => 21 |    await dispatcher.RunAsync(CoreDispatcherPriority.Normal, handler); 22 | 23 | public static async Task CallOnMainViewUiThreadAsync(DispatchedHandler handler) => 24 | await CallOnUiThreadAsync(CoreApplication.MainView.CoreWindow.Dispatcher, handler); 25 | ``` 26 | 27 | ## Usage 28 | 29 | ```C# 30 | // Single-view app can assume the UI thread is the main view (since there is only one). 31 | private async void NetworkInformation_NetworkStatusChanged(object sender) 32 | { 33 | await CallOnMainViewUiThreadAsync(() => 34 | { 35 | // Update the UI to reflect the current network status. 36 | }); 37 | } 38 | 39 | // Multi-view app should use the dispatcher for the UI thread they want to run on. 40 | private async void NetworkInformation_NetworkStatusChanged(object sender) 41 | { 42 | await CallOnUiThreadAsync(this.Dispatcher, () => 43 | { 44 | // Update this page's UI to reflect the current network status. 45 | } 46 | } 47 | ``` 48 | 49 | ## See also 50 | 51 | [CoreDispatcher class](https://msdn.microsoft.com/library/windows/apps/windows.ui.core.coredispatcher.aspx) 52 | [Lambda expressions](https://msdn.microsoft.com/library/bb397687.aspx) (anonymous methods using the "=>" syntax) 53 | 54 | The [UWP Community Toolkit](http://docs.uwpcommunitytoolkit.com/en/master/) includes an extended version of this task snippet in the form of a DispatcherHelper class 55 | ([source](https://github.com/Microsoft/UWPCommunityToolkit/blob/master/Microsoft.Toolkit.Uwp/Helpers/DispatcherHelper.cs), 56 | [docs](http://docs.uwpcommunitytoolkit.com/en/master/helpers/DispatcherHelper/)). 57 | -------------------------------------------------------------------------------- /tasks/UI-thread-task-await-from-background-thread.md: -------------------------------------------------------------------------------- 1 | 5 | 6 | # Await a UI task sent from a background thread 7 | 8 | Enables code running on a background thread to await a task that must run on the UI thread. 9 | 10 | Normally, you can update your UI from a background thread 11 | by calling `Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => /* update the UI */)`. 12 | However, this merely schedules the work on the UI thread and returns immediately, 13 | even if the task is to await user input in a popup box. 14 | It also does not provide a way for the task to return a result to the caller. 15 | 16 | RunTaskAsync provides an alternative that uses TaskCompletionSource in combination with RunAsync to return a Task 17 | that you can await from your background thread, thereby pausing execution until the UI task completes. 18 | 19 | Because RunTaskAsync is an extension method, you call it as if it were a method on Dispatcher: 20 | `var result = await Dispatcher.RunTaskAsync(async () => { ...; return value; });` 21 | 22 | ```C# 23 | using System; 24 | using System.Threading.Tasks; 25 | using Windows.UI.Core; 26 | 27 | public static class DispatcherTaskExtensions 28 | { 29 | public static async Task RunTaskAsync(this CoreDispatcher dispatcher, 30 | Func> func, CoreDispatcherPriority priority = CoreDispatcherPriority.Normal) 31 | { 32 | var taskCompletionSource = new TaskCompletionSource(); 33 | await dispatcher.RunAsync(priority, async () => 34 | { 35 | try 36 | { 37 | taskCompletionSource.SetResult(await func()); 38 | } 39 | catch (Exception ex) 40 | { 41 | taskCompletionSource.SetException(ex); 42 | } 43 | }); 44 | return await taskCompletionSource.Task; 45 | } 46 | 47 | // There is no TaskCompletionSource so we use a bool that we throw away. 48 | public static async Task RunTaskAsync(this CoreDispatcher dispatcher, 49 | Func func, CoreDispatcherPriority priority = CoreDispatcherPriority.Normal) => 50 | await RunTaskAsync(dispatcher, async () => { await func(); return false; }, priority); 51 | } 52 | ``` 53 | 54 | ## Usage 55 | 56 | ```C# 57 | public static async Task MyMethod() 58 | { 59 | System.Diagnostics.Debug.WriteLine("MyMethod() is running"); 60 | var buttonLabel = await CoreWindow.GetForCurrentThread().Dispatcher.RunTaskAsync(async () => 61 | { 62 | var popup = new Windows.UI.Popups.MessageDialog("Alert", 63 | "MyMethod() is paused. Choose a button to continue running MyMethod()"); 64 | popup.Commands.Add(new Windows.UI.Popups.UICommand("Button 1")); 65 | popup.Commands.Add(new Windows.UI.Popups.UICommand("Button 2")); 66 | popup.CancelCommandIndex = 0; 67 | var command = await popup.ShowAsync(); 68 | 69 | // The value returned by the lambda expression will be the RunTaskAsync return value. 70 | return command.Label; 71 | }); 72 | System.Diagnostics.Debug.WriteLine($"MyMethod() is running again. User clicked {buttonLabel}"); 73 | } 74 | ``` 75 | 76 | One situation where RunTaskAsync is handy is when you want to render a software bitmap to the screen 77 | from a non-ui thread, which requires using the dispatcher to run async code on the UI thread. 78 | 79 | ```C# 80 | using System.Threading.Tasks; 81 | using Windows.Graphics.Imaging; 82 | using Windows.UI.Core; 83 | using Windows.UI.Xaml.Controls; 84 | using Windows.UI.Xaml.Media.Imaging; 85 | 86 | public static async Task RenderToImageElement( 87 | Image imageElement, SoftwareBitmap softwareBitmap) 88 | { 89 | // Changes to imageElement must happen on the UI thread. 90 | await imageElement.Dispatcher.RunTaskAsync(async () => 91 | { 92 | if (softwareBitmap != null) 93 | { 94 | var imageSource = new SoftwareBitmapSource(); 95 | await imageSource.SetBitmapAsync(softwareBitmap); 96 | imageElement.Source = imageSource; 97 | } 98 | else 99 | { 100 | // Clear the image element. 101 | imageElement.Source = null; 102 | } 103 | }); 104 | } 105 | ``` 106 | 107 | ## See also 108 | 109 | [CoreDispatcher class](https://msdn.microsoft.com/library/windows/apps/windows.ui.core.coredispatcher.aspx) 110 | [CoreDispatcher.RunAsync method](https://msdn.microsoft.com/library/windows/apps/windows.ui.core.coredispatcher.runasync.aspx) 111 | [TaskCompletionSource class](https://msdn.microsoft.com/library/dd449174.aspx) 112 | [Lambda expressions](https://msdn.microsoft.com/library/bb397687.aspx) (anonymous methods using the "=>" syntax) 113 | [Extension methods](https://msdn.microsoft.com/en-us/library/bb383977.aspx) 114 | [Interpolated strings](https://msdn.microsoft.com/library/dn961160.aspx) (strings with a $ prefix) 115 | 116 | The [UWP Community Toolkit](http://docs.uwpcommunitytoolkit.com/en/master/) includes an extended version of this task snippet in the form of a DispatcherHelper class 117 | ([source](https://github.com/Microsoft/UWPCommunityToolkit/blob/master/Microsoft.Toolkit.Uwp/Helpers/DispatcherHelper.cs), 118 | [docs](http://docs.uwpcommunitytoolkit.com/en/master/helpers/DispatcherHelper/)). 119 | -------------------------------------------------------------------------------- /tasks/UI-update-after-delay.md: -------------------------------------------------------------------------------- 1 | 5 | 6 | # Update the UI after a delay 7 | 8 | Performs the specified action after the specified number of milliseconds. 9 | 10 | ```C# 11 | using System; 12 | using System.Threading.Tasks; 13 | using Windows.ApplicationModel.Core; 14 | 15 | public static void DoAfterDelay(int millisecondsDelay, Action action) 16 | { 17 | var withoutAwait = CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync( 18 | Windows.UI.Core.CoreDispatcherPriority.Normal, 19 | async () => { await Task.Delay(millisecondsDelay); action(); }); 20 | } 21 | ``` 22 | 23 | Although DoAfterDelay uses async in its implementation, it is not an async method. This is because 24 | callers do not need to await any results. Therefore, it does not await its RunAsync call and does not 25 | return a Task. (The withoutAwait variable is present only to suppress the warning about not using "await".) 26 | DoAfterDelay could be an "async void" method, but this is not recommended except with event handlers 27 | because callers expect to be able to await async methods. 28 | 29 | ## Usage 30 | 31 | One scenario where this method is useful is to hide a temporary message after displaying it briefly. 32 | 33 | ```C# 34 | using Windows.UI.Xaml; 35 | using Windows.UI.Xaml.Controls; 36 | 37 | // Normally declared in XAML. 38 | TextBlock AlertMessage { get; } = new TextBlock { Text = "Alert!" }; 39 | 40 | public void ShowAlertForFiveSeconds() 41 | { 42 | AlertMessage.Visibility = Visibility.Visible; 43 | DoAfterDelay(5000, () => AlertMessage.Visibility = Visibility.Collapsed); 44 | } 45 | ``` 46 | 47 | ## See also 48 | 49 | [CoreDispatcher.RunAsync method](https://msdn.microsoft.com/library/windows/apps/windows.ui.core.coredispatcher.runasync.aspx) 50 | 51 | [Task.Delay method](https://msdn.microsoft.com/library/hh139096.aspx) 52 | [Lambda expressions](https://msdn.microsoft.com/library/bb397687.aspx) (anonymous methods using the "=>" syntax) 53 | 54 | This method is used by the [RSS Reader](https://github.com/Microsoft/Windows-appsample-rssreader/blob/master/RssReader/ViewModels/MainViewModel.cs#L257-L266) 55 | sample to hide a temporary message. 56 | -------------------------------------------------------------------------------- /tasks/UI-updates-with-a-timer.md: -------------------------------------------------------------------------------- 1 | 5 | 6 | # Update the UI from a periodic timer 7 | 8 | Performs the specified action at the specified interval in minutes. 9 | 10 | ```C# 11 | using System; 12 | using Windows.UI.Xaml; 13 | 14 | public static void StartTimer(int intervalInMinutes, Action action) 15 | { 16 | var timer = new DispatcherTimer(); 17 | timer.Interval = new TimeSpan(0, intervalInMinutes, 0); 18 | timer.Tick += (s, e) => action(); 19 | timer.Start(); 20 | } 21 | ``` 22 | 23 | ## Usage 24 | 25 | ```C# 26 | StartTimer(5, () => 27 | { 28 | // Do something every five minutes. 29 | }); 30 | ``` 31 | 32 | ## See also 33 | 34 | [DispatcherTimer class](https://msdn.microsoft.com/library/windows/apps/windows.ui.xaml.dispatchertimer.aspx) 35 | [Lambda expressions](https://msdn.microsoft.com/library/bb397687.aspx) (anonymous methods using the "=>" syntax) 36 | 37 | The [TrafficApp sample](https://github.com/Microsoft/Windows-appsample-trafficapp) uses this method to 38 | [update location travel info and freshness timestamps](https://github.com/Microsoft/Windows-appsample-trafficapp/blob/master/TrafficApp/MainPage.xaml.cs#L121-L125). -------------------------------------------------------------------------------- /tasks/User-info.md: -------------------------------------------------------------------------------- 1 | 5 | 6 | # Get user info 7 | 8 | Helpers for getting basic info about the current system user, such as their name or domain. 9 | 10 | Before calling these methods, you must enable the **User Account Information** capability in your app's manifest file. 11 | Otherwise, they will always return an empty string. 12 | 13 | ```C# 14 | using System; 15 | using System.Threading.Tasks; 16 | using Windows.System; 17 | 18 | public static class UserInfoHelper 19 | { 20 | public static async Task GetUserAccountNameAsync() => 21 | await GetUserPropertyAsync(KnownUserProperties.AccountName); 22 | 23 | public static async Task GetUserDisplayNameAsync() => 24 | await GetUserPropertyAsync(KnownUserProperties.DisplayName); 25 | 26 | public static async Task GetUserDomainNameAsync() => 27 | await GetUserPropertyAsync(KnownUserProperties.DomainName); 28 | 29 | public static async Task GetUserFirstNameAsync() => 30 | await GetUserPropertyAsync(KnownUserProperties.FirstName); 31 | 32 | public static async Task GetUserLastNameAsync() => 33 | await GetUserPropertyAsync(KnownUserProperties.LastName); 34 | 35 | public static async Task GetUserPrincipalNameAsync() => 36 | await GetUserPropertyAsync(KnownUserProperties.PrincipalName); 37 | 38 | public static async Task GetUserProviderNameAsync() => 39 | await GetUserPropertyAsync(KnownUserProperties.ProviderName); 40 | 41 | private static async Task GetUserPropertyAsync(string property) 42 | { 43 | var users = await User.FindAllAsync(UserType.LocalUser, 44 | UserAuthenticationStatus.LocallyAuthenticated); 45 | object val = await users.FirstOrDefault()?.GetPropertyAsync(property); 46 | return val.ToString(); 47 | } 48 | } 49 | ``` 50 | 51 | **Note:** These methods assume your app is interested in the single, current, local system user. However, you can also get info 52 | about remotely authenticated users or more than one user at once (if your app is running on Xbox, for instance, where more 53 | than one user can log in at the same time). For more information, see the 54 | [User class](https://msdn.microsoft.com/library/windows/apps/windows.system.user.aspx) 55 | 56 | ## See also 57 | 58 | [User class](https://msdn.microsoft.com/library/windows/apps/windows.system.user.aspx) 59 | [KnownUserProperties class](https://msdn.microsoft.com/library/windows/apps/windows.system.knownuserproperties) 60 | [Lambda expressions](https://msdn.microsoft.com/library/bb397687.aspx) (anonymous methods using the "=>" syntax) 61 | --------------------------------------------------------------------------------