From 68837a4d585a7f919013ee70e97e3a3c2519dc7c Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Sat, 18 Jul 2020 17:09:20 +0200 Subject: [PATCH 01/27] Added introduction docs (and dupe toc.md) --- docs/mvvm/Introduction.md | 70 ++++++++++++ docs/toc.md | 219 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 289 insertions(+) create mode 100644 docs/mvvm/Introduction.md create mode 100644 docs/toc.md diff --git a/docs/mvvm/Introduction.md b/docs/mvvm/Introduction.md new file mode 100644 index 0000000..4dff46c --- /dev/null +++ b/docs/mvvm/Introduction.md @@ -0,0 +1,70 @@ +--- +title: Introduction to the MVVM package +author: Sergio0694 +description: An overview of how to get started with MVVM package and to the APIs it contains +keywords: windows 10, uwp, windows community toolkit, uwp community toolkit, uwp toolkit, get started, visual studio, MVVM, net core, net standard +--- + +# Introduction to the MVVM package + +The `Microsoft.Toolkit.Mvvm` package is a modern, fast and modular MVVM library, part of the Windows Community Toolkit. It's built around the following key principles: + +- **Platform and Runtime Independent** - **.NET Standard 2.0** 🚀 (UI Framework Agnostic) +- **Simple to pick-up and use** - No strict requirements on Application structure or coding-paradigms (outside of 'MVVM'ness) i.e. flexible usage +- **À la carte** - Developer able to choose the components they wish to leverage +- **Reference Implementation** - Lean and performant, provides compliments to interfaces and paradigms hinted at in the Base-Class Library, but without provided implementations. + +The fact that this package only targets .NET Standard means that it can be used on any app platform, from UWP to WinForms or WPF, to Xamarin or Uno, and more, and on any runtime from .NET Native to .NET Core, .NET Framework or Mono. The API surface is identical in all cases, which makes this library perfect to build shared backend libraries for applications. + +Follow these steps to install the MVVM package: + +1. Open an existing project in Visual studio, targeting any of the following: + - UWP (>= 10.0) + - .NET Standard (>= 1.4) + - .NET Core (>= 1.0) + - Any other framework supporting .NET Standard 2.0 and up + +2. In Solution Explorer panel, right click on your project name and select **Manage NuGet Packages**. Search for **Microsoft.Toolkit.Mvvm** and install it. + + ![NuGet Packages](../resources/images/ManageNugetPackages.png "Manage NuGet Packages Image") + +3. Add a using directive in your C# files to use the new APIs: + + ```c# + using Microsoft.Toolkit.Mvvm; + ``` + +4. If you want so see some code samples, you can either read through the other docs pages for the MVVM package, or have a look at the various [unit tests](https://github.com/windows-toolkit/WindowsCommunityToolkit/tree/master/UnitTests/UnitTests.Shared/Mvvm) for the project. + +## When should I use this package? + +The idea for this package would be to have a series of common, self-contained, lightweight types: + +- **Microsoft.Toolkit.Mvvm.ComponentModel** + - `ObservableObject` + - `ObservableRecipient` +- **Microsoft.Toolkit.Mvvm.DependencyInjection** + - `Ioc` +- **Microsoft.Toolkit.Mvvm.Input** + - `RelayCommand` + - `RelayCommand` + - `AsyncRelayCommand` + - `AsyncRelayCommand` + - `IRelayCommand` + - `IRelayCommand` + - `IAsyncRelayCommand` + - `IAsyncRelayCommand` +- **Microsoft.Toolkit.Mvvm.Messaging** + - `Messenger` + - `IMessenger` +- **Microsoft.Toolkit.Mvvm.Messaging.Messages** + - `PropertyChangedMessage` + - `RequestMessage` + - `AsyncRequestMessage` + - `CollectionRequestMessage` + - `AsyncCollectionRequestMessage` + - `ValueChangedMessage` + +These types can be used as a base to build modern apps using the MVVM pattern, as they provide a starting implementation of all the main primitives that are necessary (property change notifications, commands, dependency injection, etc.). These types alone are usually enough for many users building apps using the MVVM toolkit, without the need to add additional external references. + +One key point of this package is also to offer as much flexibility as possible: developers are free to pick and choose which components to use, and all the available types are loosely coupled so that it's possible to just pick as many of them as needed and only use them in applications. There is no requirement to go "all-in" with a specific series of all encompassing APIs, nor is there a set of mandatory patterns that need to be followed when building apps using these helpers. It's really up to each developer to combine these building blocks in the way that best fit their needs. diff --git a/docs/toc.md b/docs/toc.md new file mode 100644 index 0000000..f96045f --- /dev/null +++ b/docs/toc.md @@ -0,0 +1,219 @@ +# [Windows Community Toolkit Documentation](index.md) + +# Setup +## [Getting Started with the Windows Community Toolkit](Getting-Started.md) +## [Windows Community Toolkit Nuget Packages](Nuget-Packages.md) +## [Adding the Windows Community Toolkit to your Visual Studio Toolbox](Toolbox-Support.md) +## [Known Issues](knownissues.md) + +# Controls +## Controls for WPF and Windows Forms +### [InkCanvas](controls/wpf-winforms/InkCanvas.md) +### [InkToolbar](controls/wpf-winforms/InkToolbar.md) +### [MapControl](controls/wpf-winforms/MapControl.md) +### [MediaPlayerElement](controls/wpf-winforms/MediaPlayerElement.md) +### [WebView](controls/wpf-winforms/WebView.md) +#### [WebView known issues](controls/wpf-winforms/WebView-known-issues.md) +### [WebViewCompatible](controls/wpf-winforms/WebViewCompatible.md) +### [WindowsXamlHost](controls/wpf-winforms/WindowsXamlHost.md) +## [AdaptiveGridView](controls/AdaptiveGridView.md) +## [BladeView](controls/BladeView.md) +## [CameraPreview](controls/CameraPreview.md) +## [Carousel](controls/Carousel.md) +## [DataGrid](controls/DataGrid.md) +### [How to: Add a DataGrid control to a page](controls/datagrid_guidance/datagrid_basics.md) +### [How to: Customize the DataGrid control using styling and formatting options](controls/datagrid_guidance/styling_formatting_options.md) +### [How to: Display and configure Row Details](controls/datagrid_guidance/rowdetails.md) +### [How to: Configure Auto-generated columns in the DataGrid control](controls/datagrid_guidance/customize_autogenerated_columns.md) +### [How to: Group, sort and filter data using LINQ and the DataGrid control](controls/datagrid_guidance/group_sort_filter.md) +### [How to: Edit and perform input validation in the DataGrid control](controls/datagrid_guidance/editing_inputvalidation.md) +### [Sizing options in the DataGrid control](controls/datagrid_guidance/sizing_options.md) +### [Default keyboard navigation and selection patterns](controls/datagrid_guidance/keyboard_navigation_selection.md) +## [DockPanel](controls/DockPanel.md) +## [DropShadowPanel Control](controls/DropShadowPanel.md) +## [Expander Control](controls/Expander.md) +## [Eyedropper](controls/Eyedropper.md) +## [GridSplitter](controls/GridSplitter.md) +## [HeaderedContentControl](controls/HeaderedContentControl.md) +## [HeaderedItemsControl](controls/HeaderedItemsControl.md) +## [HeaderedTextBlock](controls/HeaderedTextBlock.md) +## [ImageCropper](controls/ImageCropper.md) +## [ImageEx](controls/ImageEx.md) +## [InAppNotification](controls/InAppNotification.md) +## [InfiniteCanvas](controls/InfiniteCanvas.md) +## [LayoutTransformControl](controls/LayoutTransformControl.md) +## [Loading](controls/Loading.md) +## [MarkdownTextBlock](controls/MarkdownTextBlock.md) +## [MasterDetailsView](controls/MasterDetailsView.md) +## [Menu Control](controls/Menu.md) +## [OrbitView](controls/OrbitView.md) +## [RadialGauge](controls/RadialGauge.md) +## [RadialProgressBar](controls/RadialProgressBar.md) +## [RangeSelector](controls/RangeSelector.md) +## [RemoteDevicePicker](controls/RemoteDevicePicker.md) +## [RotatorTile](controls/RotatorTile.md) +## [ScrollHeader](controls/ScrollHeader.md) +## [StaggeredLayout](controls/layout/StaggeredLayout.md) + +## [StaggeredPanel](controls/StaggeredPanel.md) +## [TabView](controls/TabView.md) +## [TextToolbar](controls/TextToolbar.md) +## [TileControl](controls/TileControl.md) +## [TokenizingTextBox](controls/TokenizingTextBox.md) +## [UniformGrid](controls/UniformGrid.md) +## [WrapLayout](controls/layout/WrapLayout.md) + +## [WrapPanel](controls/WrapPanel.md) + +# Animations +## [AnimationSet](animations/AnimationSet.md) +## [Blur](animations/Blur.md) +## [Composition Animations](animations/CompositionAnimations.md) +## [Connected Animations](animations/ConnectedAnimations.md) +## [ExpressionBuilder](animations/Expressions.md) +## [Fade](animations/Fade.md) +## [FadeHeader](animations/FadeHeader.md) +## [Implicit Animations](animations/ImplicitAnimations.md) +## [Light](animations/Light.md) +## [Lottie](animations/Lottie.md) +### [Getting Started with Lottie-Windows](animations/lottie-scenarios/getting_started_json.md) +### [Using Codegen](animations/lottie-scenarios/getting_started_codegen.md) +### [JSON versus Codegen](animations/lottie-scenarios/json_codegen.md) +### [Configuring Animation Playback](animations/lottie-scenarios/playback.md) +### [Interactive Segments on an Animation Timeline](animations/lottie-scenarios/segments.md) +### [The Asynchronous Play Method](animations/lottie-scenarios/async_play.md) +### [Handling Failure and Down-level](animations/lottie-scenarios/fallback.md) +## [Offset](animations/Offset.md) +## [ReorderGridAnimation](animations/ReorderGrid.md) +## [Rotate](animations/Rotate.md) +## [Saturation](animations/Saturation.md) +## [Scale](animations/Scale.md) + +# Brushes +## [AcrylicBrush](brushes/AcrylicBrush.md) +## [BackdropBlurBrush](brushes/BackdropBlurBrush.md) +## [BackdropGammaTransferBrush](brushes/BackdropGammaTransferBrush.md) +## [BackdropInvertBrush](brushes/BackdropInvertBrush.md) +## [BackdropSaturationBrush](brushes/BackdropSaturationBrush.md) +## [BackdropSepiaBrush](brushes/BackdropSepiaBrush.md) +## [ImageBlendBrush](brushes/ImageBlendBrush.md) +## [PipelineBrush](brushes/PipelineBrush.md) +## [RadialGradientBrush](brushes/RadialGradientBrush.md) +## [TilesBrush](brushes/TilesBrush.md) + +# Extensions +## [ArrayExtensions](extensions/ArrayExtensions.md) +## [Composition Visual Layer Extensions](extensions/VisualExtensions.md) +## [FrameworkElementExtensions](extensions/FrameworkElementExtensions.md) +## [HyperlinkExtensions](extensions/HyperlinkExtensions.md) +## [IconMarkupExtensions](extensions/IconMarkupExtensions.md) +## [ListViewExtensions](extensions/ListViewExtensions.md) +## [Logical Tree](extensions/LogicalTree.md) +## [Matrix Extensions](extensions/MatrixExtensions.md) +### [Extra Matrix Helpers](extensions/MatrixHelperEx.md) +### [Transform Extensions](extensions/TransformExtensions.md) +## [Mouse Cursor](extensions/MouseCursor.md) +## [NullableBoolMarkup](extensions/NullableBoolMarkup.md) +## [ScrollViewerExtensions](extensions/ScrollViewerExtensions.md) +## [StringExtensions](extensions/StringExtensions.md) +## [SurfaceDialTextboxHelper](extensions/SurfaceDialTextboxHelper.md) +## [TextBoxMask](extensions/TextBoxMask.md) +## [TextBoxRegex](extensions/TextBoxRegex.md) +## [UIElementExtensions](extensions/UIElementExtensions.md) +## [ViewExtensions](extensions/ViewExtensions.md) +## [Visual Tree](extensions/VisualTree.md) +## [WebViewExtensions](extensions/WebViewExtensions.md) + +# Collections +## [Observable Groups](collections/ObservableGroups.md) + +# Microsoft Graph +## Controls +### [LoginButton](graph/controls/LoginButton.md) +### [PersonView](graph/controls/PersonView.md) +### [PeoplePicker](graph/controls/PeoplePicker.md) +## Providers +### [InteractiveProviderBehavior](graph/providers/InteractiveProviderBehavior.md) +### [MockProviderBehavior](graph/providers/MockProviderBehavior.md) + +# Helpers +## [AdvancedCollectionView](helpers/AdvancedCollectionView.md) +## [BackgroundTaskHelper](helpers/BackgroundTaskHelper.md) +## [BindableValueHolder](helpers/BindableValueHolder.md) +## [BluetoothLEHelper](helpers/BluetoothLEHelper.md) +## [CameraHelper](helpers/CameraHelper.md) +## [Colors](helpers/Colors.md) +## [Converters](helpers/Converters.md) +## [DeepLinkParser](helpers/DeepLinkParsers.md) +## [DispatcherHelper](helpers/DispatcherHelper.md) +## [HttpHelper](helpers/HttpHelper.md) +## [HttpHelperRequest](helpers/HttpHelperRequest.md) +## [HttpHelperResponse](helpers/HttpHelperResponse.md) +## [ImageCache](helpers/ImageCache.md) +## [IncrementalLoadingCollection](helpers/IncrementalLoadingCollection.md) +## [NetworkHelper](helpers/NetworkHelper.md) +## [ObjectStorage](helpers/ObjectStorage.md) +## [ObjectSerializer](helpers/ObjectSerializer.md) +## [PrintHelper](helpers/PrintHelper.md) +## [RemoteDeviceHelper](helpers/RemoteDeviceHelper.md) +## [StorageFileHelper](helpers/StorageFiles.md) +## [Streams Helper](helpers/Streams.md) +## [SystemInformation](helpers/SystemInformation.md) +## [ThemeListener](helpers/ThemeListener.md) +## [Triggers](helpers/Triggers.md) +## [WeakEventListener](helpers/WeakEventListener.md) +## [ViewportBehavior](helpers/ViewportBehavior.md) + +# Services +## [Facebook Service](services/Facebook.md) +## [LinkedIn Service](services/Linkedin.md) +## [Microsoft Graph Service](services/MicrosoftGraph.md) +### [GraphLogin (WinForms)](services/GraphLogin.md) +## [Microsoft Translator Service](services/MicrosoftTranslator.md) +## [OneDrive Service](services/OneDrive.md) +## [Twitter Service](services/Twitter.md) +## [Weibo Service](services/Weibo.md) + +# Parsers +## [MarkdownParser](parsers/MarkdownParser.md) +## [RSSParser](parsers/RSSParser.md) + +# MVVM +## [Introduction](mvvm/Introduction.md) + +# High performance +## [Introduction](high-performance/Introduction.md) +## Buffers +### [MemoryOwner](high-performance/MemoryOwner.md) +### [SpanOwner](high-performance/SpanOwner.md) +### [StringPool](high-performance/StringPool.md) +## [ParallelHelper](high-performance/ParallelHelper.md) +## [Ref and ReadOnlyRef](high-performance/Ref.md) + +# Developer tools +## [AlignmentGrid](developer-tools/AlignmentGrid.md) +## [FocusTracker](developer-tools/FocusTracker.md) +## [Guard](developer-tools/Guard.md) + +# [GazeInteractionLibrary](gaze/GazeInteractionLibrary.md) + +# [Notifications](notifications/NotificationsOverview.md) + +# [Platform Specific Analyzer](platform-specific/PlatformSpecificAnalyzer.md) + +# Archive +## Animations +### [ParallaxService](archive/ParallaxService.md) +## Controls +### [HamburgerMenu](archive/HamburgerMenu.md) +### [PullToRefreshListView](archive/PullToRefreshListview.md) +### [SlidableListItem](archive/SlidableListItem.md) +## Microsoft Graph Controls +### [AadLogin](archive/graph/AadLogin.md) +### [PeoplePicker](archive/graph/PeoplePicker.md) +### [PlannerTaskList](archive/graph/PlannerTaskList.md) +### [PowerBIEmbedded](archive/graph/PowerBIEmbedded.md) +### [ProfileCard](archive/graph/ProfileCard.md) +### [SharePointFileList](archive/graph/SharePointFileList.md) +## Services +### [Bing Service](archive/Bing.md) From 8e4176f1f64bbb205245e0c9f714270f7afe90db Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Sat, 18 Jul 2020 17:20:25 +0200 Subject: [PATCH 02/27] Added ObservableObject docs --- docs/mvvm/ObservableObject.md | 100 ++++++++++++++++++++++++++++++++++ docs/toc.md | 2 + 2 files changed, 102 insertions(+) create mode 100644 docs/mvvm/ObservableObject.md diff --git a/docs/mvvm/ObservableObject.md b/docs/mvvm/ObservableObject.md new file mode 100644 index 0000000..bbdaec5 --- /dev/null +++ b/docs/mvvm/ObservableObject.md @@ -0,0 +1,100 @@ +--- +title: ObservableObject +author: Sergio0694 +description: A base class for objects of which the properties must be observable +keywords: windows 10, uwp, windows community toolkit, uwp community toolkit, uwp toolkit, mvvm, componentmodel, property changed, notification, binding, net core, net standard +dev_langs: + - csharp +--- + +# ObservableObject + +The [ObservableObject](https://docs.microsoft.com/dotnet/api/microsoft.toolkit.mvvm.componentmodel.ObservableObject) is a base class for objects of which the properties must be observable, implementing the [`INotifyPropertyChanged`](https://docs.microsoft.com/dotnet/api/system.componentmodel.inotifypropertychanged) and [`INotifyPropertyChanging`](https://docs.microsoft.com/dotnet/api/system.componentmodel.inotifypropertychanging) interfaces. It can be used as a starting point for all kinds of objects that need to support property change notifications. + +## How it works + +`ObservableObject` has the following main features: + +- It provides a base implementation for `INotifyPropertyChanged` and `INotifyPropertyChanging`, exposing the `PropertyChanged` and `PropertyChanging` events. +- It provides a series of `Set` methods that can be used to easily set property values from types inheriting from `ObservableObject`, and to automatically raise the appropriate events. +- It provides the `SetAndNotifyOnCompletion` method, which is analogous to `Set` but with the ability to set `Task` properties and raise the notification events automatically when the assigned tasks are completed. +- It exposes the `OnPropertyChanged` and `OnPropertyChanging` methods, which can be overridden in derived types to customize how the notification events are raised. + +## Simple property + +Here's an example of how to implement notification support to a custom property: + +```csharp +public class User : ObservableObject +{ + private string name; + + public string Name + { + get => name; + set => Set(ref name, value); + } +} +``` + +The provided `Set(ref T, T, string)` method can be used to check the current value of the property, and update it if needed, and then also raise the relevant events automatically. The property name is automatically captured through the use of the `[CallerMemberName]` attribute, so there's no need to manually specify which property is being updated. + +## Wrapping a non-observable model + +A common scenario, for instance when working with database items, is to create a wrapping "bindable" model that simply relays property to the database model, and raises the property changed notifications when needed. This is also needed when we want to inject notification support to models we don't own, that don't directly implement the `INotifyPropertyChanged` interface. `ObservableObject` provides a dedicated method to make this process simpler. For the following example, imagine that `User` was a model directly mapping a database table, without inheriting from `ObservableObject`: + +```csharp +public class ObservableUser : ObservableObject +{ + private readonly User user; + + public ObservableUser(User user) => this.user = user; + + public string Name + { + get => user.Name; + set => Set(() => user.Name, value); + } +} +``` + +The `Set(Expression>, T, string)` method makes creating these wrapping properties extremely simple, as it takes of both retrieving and setting the target properties while providing an extremely compact API to do so. + +## Handling `Task` properties + +Lastly, what if the property we want to set is a `Task`? In that case, we'd wait to also raise the notification event when the task completes, so that we could bind to that property eg. to display some loading indicator or some other status info on the operation represented by the task. `ObservableObject` has a useful API for this scenario as well: + +```csharp +public class MyModel : ObservableObject +{ + private Task requestTask; + + public Task RequestTask + { + get => requestTask; + set => SetAndNotifyOnCompletion(ref requestTask, () => requestTask, value); + } + + public void RequestValue() + { + LoadingTask = WebService.LoadMyValueAsync(); + } +} +``` + +Here the `SetAndNotifyOnCompletion(ref TTask, Expression>, TTask, string)` method will take care of updating the target field, then monitoring the new task, if present, and raising the notification event again when that task completes. This way, it's possible to just bind to that task property and to be notified when its status changes. + +## Sample Code + +You can find more examples in our [unit tests](https://github.com/Microsoft/WindowsCommunityToolkit//blob/master/UnitTests/UnitTests.Shared/Mvvm) + +## Requirements + +| Device family | Universal, 10.0.16299.0 or higher | +| --- | --- | +| Namespace | Microsoft.Toolkit.HighPerformance | +| NuGet package | [Microsoft.Toolkit.HighPerformance](https://www.nuget.org/packages/Microsoft.Toolkit.HighPerformance/) | + +## API + +* [ObservableObject source code](https://github.com/Microsoft/WindowsCommunityToolkit//blob/master/Microsoft.Toolkit.Mvvm/ComponentModel/ObservableObject.cs) diff --git a/docs/toc.md b/docs/toc.md index f96045f..f5f8dc2 100644 --- a/docs/toc.md +++ b/docs/toc.md @@ -180,6 +180,8 @@ # MVVM ## [Introduction](mvvm/Introduction.md) +## ComponentModel +### [ObservableObject](mvvm/ObservableObject.md) # High performance ## [Introduction](high-performance/Introduction.md) From 23f514fffca1c0c65ccb3a753173a358b68a9e19 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Sat, 18 Jul 2020 17:53:03 +0200 Subject: [PATCH 03/27] Added RelayCommand docs --- docs/mvvm/RelayCommand.md | 83 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 docs/mvvm/RelayCommand.md diff --git a/docs/mvvm/RelayCommand.md b/docs/mvvm/RelayCommand.md new file mode 100644 index 0000000..20cdb51 --- /dev/null +++ b/docs/mvvm/RelayCommand.md @@ -0,0 +1,83 @@ +--- +title: RelayCommand +author: Sergio0694 +description: A command whose sole purpose is to relay its functionality to other objects by invoking delegates +keywords: windows 10, uwp, windows community toolkit, uwp community toolkit, uwp toolkit, mvvm, componentmodel, property changed, notification, binding, command, delegate, net core, net standard +dev_langs: + - csharp +--- + +# RelayCommand and RelayCommand<T> + +The [`RelayCommand`](https://docs.microsoft.com/dotnet/api/microsoft.toolkit.mvvm.input.RelayCommand) and [`RelayCommand`](https://docs.microsoft.com/dotnet/api/microsoft.toolkit.mvvm.input.RelayCommand-1) are two `ICommand` implementations that can be used to expose a specified method or delegate to the view. These types act as a way to bind commands from the viewmodel to UI elements. + +## How they work + +`RelayCommand` and `RelayCommand` have the following main features: + +- They provide a base implementation for the `ICommand` interface. +- They also implement the `IRelayCommand` (and `IRelayCommand`) interface, which exposes a `NotifyCanExecuteChanged` method that can be used to externally raise the `CanExecuteChanged` event when needed. +- They expose constructors taking delegates like `Action` and `Func`, which allow to wrap either standard methods or lambda expressions. + +## Working with `ICommand` + +Here's an example of how to setup a simple command: + +```csharp +public class MyViewModel : ObservableObject +{ + public MyViewModel() + { + IncrementCounterCommand = new RelayCommand(IncrementCounter); + } + + private int counter; + + public int Counter + { + get => counter; + private set => Set(ref counter, value); + } + + public ICommand IncrementCounterCommand { get; } + + private void IncrementCounter() => Counter++; +} +``` + +And the relative UI could then be (using WinUI XAML): + +```xml + + + + + + + +