You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/mvvm/AsyncRelayCommand.md
+6-16Lines changed: 6 additions & 16 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -9,7 +9,9 @@ dev_langs:
9
9
10
10
# AsyncRelayCommand and AsyncRelayCommand<T>
11
11
12
-
The [`AsyncRelayCommand`](https://docs.microsoft.com/dotnet/api/microsoft.toolkit.mvvm.input.AsyncRelayCommand) and [`AsyncRelayCommand<T>`](https://docs.microsoft.com/dotnet/api/microsoft.toolkit.mvvm.input.AsyncRelayCommand-1) are `ICommand` implementations that extend the functionalities offered by `RelayCommand`, with support for asynchronous operations.
12
+
The [`AsyncRelayCommand`](https://docs.microsoft.com/dotnet/api/microsoft.toolkit.mvvm.input.AsyncRelayCommand) and [`AsyncRelayCommand<T>`](https://docs.microsoft.com/dotnet/api/microsoft.toolkit.mvvm.input.AsyncRelayCommand-1) are `ICommand` implementations that extend the functionalities offered by [`RelayCommand`](https://docs.microsoft.com/dotnet/api/microsoft.toolkit.mvvm.input.RelayCommand), with support for asynchronous operations.
@@ -18,7 +20,7 @@ The [`AsyncRelayCommand`](https://docs.microsoft.com/dotnet/api/microsoft.toolki
18
20
- They extend the functionalities of the synchronous commands included in the library, with support for `Task`-returning delegates.
19
21
- They can wrap asynchronous functions with an additional `CancellationToken` parameter to support cancelation, and they expose a `CanBeCanceled` and `IsCancellationRequested` properties, as well as a `Cancel` method.
20
22
- They expose an `ExecutionTask` property that can be used to monitor the progress of a pending operation, and an `IsRunning` that can be used to check when an operation completes. This is particularly useful to bind a command to UI elements such as loading indicators.
21
-
- They implement the `IAsyncRelayCommand` and `IAsyncRelayCommand<T>` interfaces, which means that viewmodel can easily expose commands using these to reduce the tight coupling between types. For instance, this makes it easier to replace a command with a custom implementation exposing the same public API surface, if needed.
23
+
- They implement the [`IAsyncRelayCommand`](https://docs.microsoft.com/dotnet/api/microsoft.toolkit.mvvm.input.IAsyncRelayCommand) and [`IAsyncRelayCommand<T>`](https://docs.microsoft.com/dotnet/api/microsoft.toolkit.mvvm.input.IAsyncRelayCommand-1) interfaces, which means that viewmodel can easily expose commands using these to reduce the tight coupling between types. For instance, this makes it easier to replace a command with a custom implementation exposing the same public API surface, if needed.
22
24
23
25
## Working with asynchronous commands
24
26
@@ -75,18 +77,6 @@ With the related UI code:
75
77
76
78
Upon clicking the `Button`, the command is invoked, and the `ExecutionTask` updated. When the operation completes, the property raises a notification which is reflected in the UI. In this case, both the task status and the current result of the task are displayed. Note that to show the result of the task, it is necessary to use the `TaskExtensions.GetResultOrDefault` method - this provides access to the result of a task that has not yet completed without blocking the thread (and possibly causing a deadlock).
77
79
78
-
## Sample Code
79
-
80
-
There are more examples in the [unit tests](https://github.com/Microsoft/WindowsCommunityToolkit//blob/master/UnitTests/UnitTests.Shared/Mvvm).
81
-
82
-
## Requirements
83
-
84
-
| Device family | Universal, 10.0.16299.0 or higher |
Copy file name to clipboardExpand all lines: docs/mvvm/Ioc.md
+4-13Lines changed: 4 additions & 13 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -13,6 +13,8 @@ A common pattern that can be used to increase modularity in the codebase of an a
13
13
14
14
The MVVM Toolkit doesn't provide built-in APIs to facilitate the usage of this pattern, as there already exist dedicated libraries specifically for this such as the `Microsoft.Extensions.DependencyInjection` package, which provides a fully featured and powerful DI set of APIs, and acts as an easy to setup and use `IServiceProvider`. The following guide will refer to this library and provide a series of examples of how to integrate it into applications using the MVVM pattern.
The first step is to declare an `IServiceProvider` instance, and to initialize all the necessary services, usually at startup. For instance, on UWP (but a similar setup can be used on other frameworks too):
@@ -147,17 +149,6 @@ public ContactsView()
147
149
148
150
For more info about `Microsoft.Extensions.DependencyInjection`, see [here](https://docs.microsoft.com/aspnet/core/fundamentals/dependency-injection).
149
151
150
-
## Sample Code
151
-
152
-
There are more examples in the [unit tests](https://github.com/Microsoft/WindowsCommunityToolkit//blob/master/UnitTests/UnitTests.Shared/Mvvm).
153
-
154
-
## Requirements
155
-
156
-
| Device family | Universal, 10.0.16299.0 or higher |
Copy file name to clipboardExpand all lines: docs/mvvm/Messenger.md
+7-18Lines changed: 7 additions & 18 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -11,11 +11,13 @@ dev_langs:
11
11
12
12
The [`IMessenger`](https://docs.microsoft.com/dotnet/api/microsoft.toolkit.mvvm.Messaging.IMessenger) interface is a contract for types that can be used to exchange messages between different objects. This can be useful to decouple different modules of an application without having to keep strong references to types being referenced. It is also possible to send messages to specific channels, uniquely identified by a token, and to have different messengers in different sections of an application. The MVVM Toolkit provides two implementations out of the box: [`WeakReferenceMessenger`](https://docs.microsoft.com/dotnet/api/microsoft.toolkit.mvvm.Messaging.WeakReferenceMessenger) and [`StrongReferenceMessenger`](https://docs.microsoft.com/dotnet/api/microsoft.toolkit.mvvm.Messaging.StrongReferenceMessenger): the former uses weak references internally, offering automatic memory management for recipients, while the latter uses strong references and requires developers to manually unsubscribe their recipients when they're no longer needed (more details about how to unregister message handlers can be found below), but in exchange for that offers better performance and far less memory usage.
Types implementing `IMessenger` are responsible for maintaining links between recipients (receivers of messages) and their registered message types, with relative message handlers. Any object can be registered as a recipient for a given message type using a message handler, which will be invoked whenever the `IMessenger` instance is used to send a message of that type. It is also possible to send messages through specific communication channels (each identified by a unique token), so that multiple modules can exchange messages of the same type without causing conflicts. Messages sent without a token use the default shared channel.
17
19
18
-
There are two ways to perform message registration: either through the `IRecipient<TMessage>` interface, or using a `MessageHandler<TRecipient, TMessage>` delegate acting as message handler. The first lets you register all the handlers with a single call to the `RegisterAll` extension, which automatically registers the recipients of all the declared message handlers, while the latter is useful when you need more flexibility or when you want to use a simple lambda expression as a message handler.
20
+
There are two ways to perform message registration: either through the [`IRecipient<TMessage>`](https://docs.microsoft.com/dotnet/api/microsoft.toolkit.mvvm.Messaging.irecipient-1) interface, or using a [`MessageHandler<TRecipient, TMessage>`](https://docs.microsoft.com/dotnet/api/microsoft.toolkit.mvvm.Messaging.messagehandler-2) delegate acting as message handler. The first lets you register all the handlers with a single call to the `RegisterAll` extension, which automatically registers the recipients of all the declared message handlers, while the latter is useful when you need more flexibility or when you want to use a simple lambda expression as a message handler.
19
21
20
22
Both `WeakReferenceMessenger` and `StrongReferenceMessenger` also expose a `Default` property that offers a thread-safe implementation built-in into the package. It is also possible to create multiple messenger instances if needed, for instance if a different one is injected with a DI service provider into a different module of the app (for instance, multiple windows running in the same process).
Another useful feature of messenger instances is that they can also be used to request values from a module to another. In order to do so, the package includes a base `RequestMessage<T>` class, which can be used like so:
96
+
Another useful feature of messenger instances is that they can also be used to request values from a module to another. In order to do so, the package includes a base [`RequestMessage<T>`](https://docs.microsoft.com/dotnet/api/microsoft.toolkit.mvvm.Messaging.Messages.RequestMessage-1) class, which can be used like so:
95
97
96
98
```csharp
97
99
// Create a message
@@ -114,7 +116,7 @@ User user = WeakReferenceMessenger.Default.Send<LoggedInUserRequestMessage>();
114
116
115
117
The `RequestMessage<T>` class includes an implicit converter that makes the conversion from a `LoggedInUserRequestMessage` to its contained `User` object possible. This will also check that a response has been received for the message, and throw an exception if that's not the case. It is also possible to send request messages without this mandatory response guarantee: just store the returned message in a local variable, and then manually check whether a response value is available or not. Doing so will not trigger the automatic exception if a response is not received when the `Send` method returns.
116
118
117
-
The same namespace also includes base requests message for other scenarios: `AsyncRequestMessage<T>`, `CollectionRequestMessage<T>` and `AsyncCollectionRequestMessage<T>`.
119
+
The same namespace also includes base requests message for other scenarios: [`AsyncRequestMessage<T>`](https://docs.microsoft.com/dotnet/api/microsoft.toolkit.mvvm.Messaging.Messages.AsyncRequestMessage-1), [`CollectionRequestMessage<T>`](https://docs.microsoft.com/dotnet/api/microsoft.toolkit.mvvm.Messaging.Messages.CollectionRequestMessage-1) and [`AsyncCollectionRequestMessage<T>`](https://docs.microsoft.com/dotnet/api/microsoft.toolkit.mvvm.Messaging.Messages.AsyncCollectionRequestMessage-1).
Copy file name to clipboardExpand all lines: docs/mvvm/ObservableObject.md
+5-14Lines changed: 5 additions & 14 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -11,6 +11,8 @@ dev_langs:
11
11
12
12
The [`ObservableObject`](https://docs.microsoft.com/dotnet/api/microsoft.toolkit.mvvm.componentmodel.ObservableObject) is a base class for objects that are observable by 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.
`ObservableObject` has the following main features:
@@ -94,22 +96,11 @@ public class MyModel : ObservableObject
94
96
}
95
97
```
96
98
97
-
Here the `SetPropertyAndNotifyOnCompletion<T>(ref TaskNotifier<T>, Task<T>, string)` method will take care of updating the target field, monitoring the new task, if present, and raising the notification event when that task completes. This way, it's possible to just bind to a task property and to be notified when its status changes. The `TaskNotifier<T>` is a special type exposed by `ObservableObject` that wraps a target `Task<T>` instance and enables the necessary notification logic for this method. The `TaskNotifier` type is also available to use directly if you have a general `Task` only.
99
+
Here the `SetPropertyAndNotifyOnCompletion<T>(ref TaskNotifier<T>, Task<T>, string)` method will take care of updating the target field, monitoring the new task, if present, and raising the notification event when that task completes. This way, it's possible to just bind to a task property and to be notified when its status changes. The [`TaskNotifier<T>`](https://docs.microsoft.com/dotnet/api/microsoft.toolkit.mvvm.componentmodel.ObservableObject.TaskNotifier-1) is a special type exposed by `ObservableObject` that wraps a target `Task<T>` instance and enables the necessary notification logic for this method. The [`TaskNotifier`](https://docs.microsoft.com/dotnet/api/microsoft.toolkit.mvvm.componentmodel.ObservableObject.TaskNotifier) type is also available to use directly if you have a general `Task` only.
98
100
99
101
> [!NOTE]
100
102
> The `SetPropertyAndNotifyOnCompletion` method is meant to replace the usage of the `NotifyTaskCompletion<T>` type from the `Microsoft.Toolkit` package. If this type was being used, it can be replaced with just the inner `Task` (or `Task<TResult>`) property, and then the `SetPropertyAndNotifyOnCompletion` method can be used to set its value and raise notification changes. All the properties exposed by the `NotifyTaskCompletion<T>` type are available directly on `Task` instances.
101
103
102
-
## Sample Code
103
-
104
-
There are more examples in the [unit tests](https://github.com/Microsoft/WindowsCommunityToolkit//blob/master/UnitTests/UnitTests.Shared/Mvvm).
105
-
106
-
## Requirements
107
-
108
-
| Device family | Universal, 10.0.16299.0 or higher |
0 commit comments