Chinook.DataLoader.DynamicMvvm
0.10.0
See the version list below for details.
dotnet add package Chinook.DataLoader.DynamicMvvm --version 0.10.0
NuGet\Install-Package Chinook.DataLoader.DynamicMvvm -Version 0.10.0
<PackageReference Include="Chinook.DataLoader.DynamicMvvm" Version="0.10.0" />
paket add Chinook.DataLoader.DynamicMvvm --version 0.10.0
#r "nuget: Chinook.DataLoader.DynamicMvvm, 0.10.0"
// Install Chinook.DataLoader.DynamicMvvm as a Cake Addin #addin nuget:?package=Chinook.DataLoader.DynamicMvvm&version=0.10.0 // Install Chinook.DataLoader.DynamicMvvm as a Cake Tool #tool nuget:?package=Chinook.DataLoader.DynamicMvvm&version=0.10.0
Chinook.DataLoader
Async data loading made visually pleasant!
Getting Started
Install the latest version of Chinook.DataLoader.Uno
in your project.
Create a IDataLoader
using the builder (see below on how to use with Chinook.DynamicMvvm).
var dataLoader = DataLoaderBuilder<MyData>
.Empty
.WithName("MyDataLoader")
.WithLoadMethod(LoadData)
.Build();
Task<MyData> LoadData(CancellationToken ct)
{
// Your async operation here.
}
Add a DataLoaderView
in your xaml.
<dl:DataLoaderView Source="{Binding MyDataLoader}" />
As the task is being executed, the IDataLoader
will call its StateChanged
event which will be used by DataLoaderView
to visually represent the state of the async operation.
Features
Async data loading
The loading method of the IDataLoader
must simply return a Task
of the data type (here MyData
).
Task<MyData> LoadData(CancellationToken ct)
{
// Your async operation here.
}
This is where you would typically execute an API call or get data from any other async source.
This method receives a CancellationToken
as the operation might be cancelled.
- If the
IDataLoader
is disposed. - If another request was made and the concurrent mode is
CancelPrevious
.
Data loader states
At any given time, the IDataLoader
can be in a combination of the following states.
State | Description |
---|---|
IsLoading | Is the data loader executing a request |
Data | Last data from a successful request |
Error | Error if the request failed (if any) |
Imagine a scenario where you land on a page where the data has never been loaded before from an API.
- The system would first be on an initial state (not loading, no data, no error).
- The system would then start loading the data from the API.
- The system would then show the data returned from the API.
- You lose connection and refresh the page.
- The system notifies you that there was an error, but you still have your previous data.
This could be represented by the following state flow.
#1 #2 #3 #4 #5
IsLoading(false) -> IsLoading(true) -> IsLoading(false) -> IsLoading(true) -> IsLoading(false)
Data(null) -> Data(null) -> Data(myData) -> Data(myData) -> Data(myData)
Error(null) -> Error(null) -> Error(null) -> Error(null) -> Error(WebException)
Note: The error is cleared as soon as there is a successful request
Other useful states are available:
State | Description |
---|---|
IsInitial | Was a request ever made |
IsEmpty | Should the data be considered empty |
Triggers
As the data might need to be updated, you can trigger a new load request on a IDataLoader
using triggers.
Trigger | Description |
---|---|
ManualDataLoaderTrigger | Manually trigger a load request |
ObservableDataLoaderTrigger | Trigger a load request when the observable pushes a new value |
You can create your own triggers by inheriting from DataLoaderTriggerBase
.
Simply call RaiseLoadRequested
when a load request should be requested.
Note: DataLoaderView
has a AutoLoad
property which, as its name suggests, automatically load the data of the DataLoader
when it's displayed.
Requests and contexts
To provide metadata on the loading operation, two important pieces are used.
Metadata | Description |
---|---|
IDataLoaderRequest | Request to load data loading operation |
IDataLoaderContext | Metadata on the loading operation (key-value pair) |
You can get additional information from the IDataLoader
by adding the IDataLoaderRequest
parameter.
Task<MyData> LoadData(CancellationToken ct, IDataLoaderRequest request)
{
// This is the trigger that caused that loading operation.
var sourceTrigger = request.SourceTrigger;
// This is the context that was passed to the loading operation from the trigger.
var context = request.Context;
// Your async operation here.
}
The request is also available as part of the IDataLoaderState
.
DataLoaderView
The DataLoaderView
represents the different states of the IDataLoader
using the following visual states.
Group | State |
---|---|
DataStates | Initial |
DataStates | Data |
DataStates | Empty |
ErrorStates | NoError |
ErrorStates | Error |
LoadingStates | NotLoading |
LoadingStates | Loading |
CombinedStates | Initial_NoError_NotLoading |
CombinedStates | Initial_NoError_Loading |
CombinedStates | Initial_Error_NotLoading |
CombinedStates | Initial_Error_Loading |
CombinedStates | Data_NoError_NotLoading |
CombinedStates | Data_NoError_Loading |
CombinedStates | Data_Error_NotLoading |
CombinedStates | Data_Error_Loading |
CombinedStates | Empty_NoError_NotLoading |
CombinedStates | Empty_NoError_Loading |
CombinedStates | Empty_Error_NotLoading |
CombinedStates | Empty_Error_Loading |
You can easily define the template displayed in these states by using the following template properties.
Template | Description |
---|---|
ContentTemplate | Template used when there is data to show |
EmptyTemplate | Template used when there is no data to show |
ErrorTemplate | Template used when an error occurred |
ErrorNotificationTemplate | Template used when an error occured by there is data to show |
To avoid seeing flickery transitions between the different visual states, the DataLoaderView
supports different throttling options.
Options | Description |
---|---|
StateMinimumDuration | The minimum duration a visual state should be in |
StateChangingThrottleDelay | Delay before going to a new visual state (e.g. if the loading is really quick, you probably don't want to show a loading state) |
<dl:DataLoaderView Source="{Binding MyDataLoader}"
StateMinimumDuration="0:0:1.5"
StateChangingThrottleDelay="0:0:0.100" />
DynamicMvvm
Extension methods are available on Chinook.DynamicMvvm
to create data loaders with refresh commands.
Simply add the Chinook.DataLoader.DynamicMvvm
package to your project.
public class MyViewModel : ViewModelBase
{
public IDynamicCommand RefreshData => this.GetCommandFromDataLoaderRefresh(Data);
public IDataLoader Data => this.GetDataLoader(GetData, b => b
// You can optionally configure your data loader here
);
private async Task<MyData> GetData(CancellationToken ct)
{
// Get data from your API...
}
}
Code Snippets
You can install the Visual Studio Extension Chinook Snippets and use code snippets to quickly generate data loaders when using Chinook.DynamicMvvm.
All snippets related to IDataLoader
start with ckdl
.
Changelog
Please consult the CHANGELOG for more information about version history.
License
This project is licensed under the Apache 2.0 license - see the LICENSE file for details.
Contributing
Please read CONTRIBUTING.md for details on the process for contributing to this project.
Be mindful of our Code of Conduct.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
.NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- Chinook.DataLoader (>= 0.10.0)
- Chinook.DynamicMvvm.Abstractions (>= 1.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
2.0.0 | 11,878 | 12/22/2023 |
2.0.0-feature.Uno5Update.7 | 151 | 12/6/2023 |
2.0.0-feature.Uno5Update.4 | 1,770 | 11/28/2023 |
1.2.1-feature.Uno5Update.2 | 76 | 11/3/2023 |
1.2.0 | 55,187 | 11/22/2022 |
1.1.2 | 1,002 | 11/1/2022 |
1.1.1 | 560 | 10/12/2022 |
1.1.0 | 27,750 | 9/22/2022 |
1.1.0-feature.dotnet6.2 | 145 | 9/22/2022 |
1.1.0-feature.dotnet6.1 | 118 | 9/21/2022 |
1.0.0 | 6,053 | 8/30/2022 |
0.10.0 | 465 | 8/25/2022 |
0.10.0-dev.91 | 3,063 | 8/9/2022 |
0.10.0-dev.89 | 404 | 8/4/2022 |
0.9.0-feature.uno-ui-4.71 | 187 | 3/15/2022 |
0.7.0-dev.87 | 19,847 | 5/25/2022 |
0.7.0-dev.85 | 141 | 5/25/2022 |
0.7.0-dev.83 | 5,308 | 5/19/2022 |
0.7.0-dev.81 | 146 | 5/17/2022 |
0.7.0-dev.79 | 168 | 5/13/2022 |
0.6.0-dev.77 | 181 | 5/2/2022 |
0.6.0-dev.76 | 5,877 | 3/31/2022 |
0.5.0-feature.uno-ui-4.73 | 145 | 3/15/2022 |
0.5.0-feature.uno-ui-4.72 | 150 | 3/15/2022 |
0.5.0-feature.uno-ui-4.71 | 149 | 3/15/2022 |
0.5.0-dev.73 | 5,704 | 3/15/2022 |
0.4.0-feature.uno-ui-4.70 | 5,151 | 12/21/2021 |
0.4.0-dev.69 | 16,110 | 11/26/2021 |
0.3.0-dev.67 | 11,818 | 10/4/2021 |
0.3.0-dev.65 | 782 | 9/21/2021 |
0.3.0-dev.63 | 1,994 | 9/13/2021 |
0.3.0-dev.60 | 936 | 8/30/2021 |
0.3.0-dev.58 | 2,329 | 7/26/2021 |
0.3.0-dev.56 | 2,082 | 7/5/2021 |
0.3.0-dev.54 | 12,389 | 6/22/2021 |
0.3.0-dev.52 | 274 | 6/19/2021 |
0.3.0-dev.50 | 268 | 6/5/2021 |
0.3.0-dev.48 | 1,598 | 4/20/2021 |
0.3.0-dev.44 | 15,262 | 4/8/2021 |
0.3.0-dev.42 | 8,204 | 3/16/2021 |
0.2.0-dev.37 | 2,523 | 12/17/2020 |
0.2.0-dev.35 | 3,146 | 11/2/2020 |
0.2.0-dev.33 | 7,997 | 10/27/2020 |
0.2.0-dev.31 | 238 | 10/13/2020 |
0.2.0-dev.29 | 251 | 9/29/2020 |
0.2.0-dev.27 | 6,954 | 8/13/2020 |
0.2.0-dev.25 | 292 | 6/26/2020 |