Skip to content

Commit 001a31b

Browse files
authored
(#22) MAUI sample. (#93)
* (#22) Initial version of the MAUI application. * Updated documentation
1 parent 7662023 commit 001a31b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

80 files changed

+2944
-1384
lines changed

docs/content/samples/todoapp/maui.md

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
+++
2+
title = "MAUI"
3+
+++
4+
5+
## Run the application first
6+
7+
The MAUI sample uses an in-memory Sqlite store for storing its data. To run the application locally:
8+
9+
* [Configure Visual Studio for MAUI development](https://learn.microsoft.com/dotnet/maui/get-started/installation).
10+
* Open `samples/todoapp/Samples.TodoApp.sln` in Visual Studio.
11+
* In the Solution Explorer, right-click the `TodoApp.MAUI` project, then select **Set as Startup Project**.
12+
* Select a target (in the top bar), then press F5 to run the application.
13+
14+
The application runs on Android, iOS, and Windows. Each platform needs slightly different setup. Read the MAUI documentation for more information.
15+
16+
## Deploy a datasync server to Azure
17+
18+
Before you begin adjusting the application for offline usage, you must [deploy a datasync service](../server.md). Make a note of the URI of the service before continuing.
19+
20+
## Update the application for datasync operations
21+
22+
All the changes are isolated to the `Database/AppDbContext.cs` file.
23+
24+
1. Change the definition of the class so that it inherits from `OfflineDbContext`:
25+
26+
```csharp
27+
public class AppDbContext(DbContextOptions<AppDbContext> options) : OfflineDbContext(options)
28+
{
29+
// Rest of the class
30+
}
31+
```
32+
33+
2. Add the `OnDatasyncInitialization()` method:
34+
35+
```csharp
36+
protected override void OnDatasyncInitialization(DatasyncOfflineOptionsBuilder optionsBuilder)
37+
{
38+
HttpClientOptions clientOptions = new()
39+
{
40+
Endpoint = new Uri("https://YOURSITEHERE.azurewebsites.net/"),
41+
HttpPipeline = [new LoggingHandler()]
42+
};
43+
_ = optionsBuilder.UseHttpClientOptions(clientOptions);
44+
}
45+
```
46+
47+
Replace the Endpoint with the URI of your datasync service.
48+
49+
3. Update the `SynchronizeAsync()` method.
50+
51+
The `SynchronizeAsync()` method is used by the application to synchronize data to and from the datasync service. It is called primarily from the `MainViewModel` which drives the UI interactions for the main list.
52+
53+
```csharp
54+
public async Task SynchronizeAsync(CancellationToken cancellationToken = default)
55+
{
56+
PushResult pushResult = await this.PushAsync(cancellationToken);
57+
if (!pushResult.IsSuccessful)
58+
{
59+
throw new ApplicationException($"Push failed: {pushResult.FailedRequests.FirstOrDefault().Value.ReasonPhrase}");
60+
}
61+
62+
PullResult pullResult = await this.PullAsync(cancellationToken);
63+
if (!pullResult.IsSuccessful)
64+
{
65+
throw new ApplicationException($"Pull failed: {pullResult.FailedRequests.FirstOrDefault().Value.ReasonPhrase}");
66+
}
67+
}
68+
```
69+
70+
You can now re-run your application. Watch the console logs to show the interactions with the datasync service. Press the refresh button to synchronize data with the cloud. When you restart the application, your changes will automatically populate the database again.
71+
72+
Obviously, you will want to do much more in a "real world" application, including proper error handling, authentication, and using a Sqlite file instead of an in-memory database. This example shows off the minimum required to add datasync services to an application.

docs/content/samples/todoapp/winui3.md

Lines changed: 64 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2,44 +2,71 @@
22
title = "WinUI3"
33
+++
44

5-
You can find [our sample TodoApp for WinUI3](https://github.com/CommunityToolkit/Datasync/tree/main/samples/todoapp/TodoApp.WinUI3) on our GitHub repository. All of our logic has been placed in the `Database/AppDbContext.cs` file:
6-
7-
{{< highlight lineNos="true" type="csharp" wrap="true" title="AppDbContext.cs" >}}
8-
public class AppDbContext(DbContextOptions<AppDbContext> options) : OfflineDbContext(options)
9-
{
10-
public DbSet<TodoItem> TodoItems => Set<TodoItem>();
11-
12-
protected override void OnDatasyncInitialization(DatasyncOfflineOptionsBuilder optionsBuilder)
13-
{
14-
HttpClientOptions clientOptions = new()
15-
{
16-
Endpoint = new Uri("https://YOURSITEHERE.azurewebsites.net/"),
17-
HttpPipeline = [new LoggingHandler()]
18-
};
19-
_ = optionsBuilder.UseHttpClientOptions(clientOptions);
20-
}
5+
## Run the application first
216

22-
public async Task SynchronizeAsync(CancellationToken cancellationToken = default)
23-
{
24-
PushResult pushResult = await this.PushAsync(cancellationToken);
25-
if (!pushResult.IsSuccessful)
26-
{
27-
throw new ApplicationException($"Push failed: {pushResult.FailedRequests.FirstOrDefault().Value.ReasonPhrase}");
28-
}
29-
30-
PullResult pullResult = await this.PullAsync(cancellationToken);
31-
if (!pullResult.IsSuccessful)
32-
{
33-
throw new ApplicationException($"Pull failed: {pullResult.FailedRequests.FirstOrDefault().Value.ReasonPhrase}");
34-
}
35-
}
36-
}
37-
{{< /highlight >}}
7+
The WinUI3 sample uses an in-memory Sqlite store for storing its data. To run the application locally:
8+
9+
* [Configure Visual Studio for WinUI3 development](https://learn.microsoft.com/windows/apps/get-started/start-here).
10+
* Open `samples/todoapp/Samples.TodoApp.sln` in Visual Studio.
11+
* In the Solution Explorer, right-click the `TodoApp.WinUI3` project, then select **Set as Startup Project**.
12+
* Select a target (in the top bar), then press F5 to run the application.
13+
14+
If you bump into issues at this point, ensure you can properly develop and run WinUI3 applications outside of the datasync service.
15+
16+
## Deploy a datasync server to Azure
17+
18+
Before you begin adjusting the application for offline usage, you must [deploy a datasync service](../server.md). Make a note of the URI of the service before continuing.
19+
20+
## Update the application for datasync operations
21+
22+
All the changes are isolated to the `Database/AppDbContext.cs` file.
23+
24+
1. Change the definition of the class so that it inherits from `OfflineDbContext`:
3825

39-
To enable offline synchronization:
26+
```csharp
27+
public class AppDbContext(DbContextOptions<AppDbContext> options) : OfflineDbContext(options)
28+
{
29+
// Rest of the class
30+
}
31+
```
32+
33+
2. Add the `OnDatasyncInitialization()` method:
34+
35+
```csharp
36+
protected override void OnDatasyncInitialization(DatasyncOfflineOptionsBuilder optionsBuilder)
37+
{
38+
HttpClientOptions clientOptions = new()
39+
{
40+
Endpoint = new Uri("https://YOURSITEHERE.azurewebsites.net/"),
41+
HttpPipeline = [new LoggingHandler()]
42+
};
43+
_ = optionsBuilder.UseHttpClientOptions(clientOptions);
44+
}
45+
```
46+
47+
Replace the Endpoint with the URI of your datasync service.
48+
49+
3. Update the `SynchronizeAsync()` method.
50+
51+
The `SynchronizeAsync()` method is used by the application to synchronize data to and from the datasync service. It is called primarily from the `MainViewModel` which drives the UI interactions for the main list.
52+
53+
```csharp
54+
public async Task SynchronizeAsync(CancellationToken cancellationToken = default)
55+
{
56+
PushResult pushResult = await this.PushAsync(cancellationToken);
57+
if (!pushResult.IsSuccessful)
58+
{
59+
throw new ApplicationException($"Push failed: {pushResult.FailedRequests.FirstOrDefault().Value.ReasonPhrase}");
60+
}
61+
62+
PullResult pullResult = await this.PullAsync(cancellationToken);
63+
if (!pullResult.IsSuccessful)
64+
{
65+
throw new ApplicationException($"Pull failed: {pullResult.FailedRequests.FirstOrDefault().Value.ReasonPhrase}");
66+
}
67+
}
68+
```
4069

41-
* Switch from `DbContext` to `OfflineDbContext`.
42-
* Define your `OnDatasyncInitialization()` method (don't forget to change the URL to the URL of your datasync server).
43-
* Where appropriate, use `PushAsync()` and `PullAsync()` to communicate with the server.
70+
You can now re-run your application. Watch the console logs to show the interactions with the datasync service. Press the refresh button to synchronize data with the cloud. When you restart the application, your changes will automatically populate the database again.
4471

45-
We have placed a `SynchronizeAsync()` method on the database context, which is used in the view model for the single page we have.
72+
Obviously, you will want to do much more in a "real world" application, including proper error handling, authentication, and using a Sqlite file instead of an in-memory database. This example shows off the minimum required to add datasync services to an application.

docs/public/404.html

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,17 @@
2020
<link rel="icon" type="image/png" sizes="32x32" href="/favicon/favicon-32x32.png">
2121
<link rel="icon" type="image/png" sizes="16x16" href="/favicon/favicon-16x16.png">
2222
<link rel="manifest" href="/favicon/site.webmanifest">
23-
<link href="/Datasync/css/fontawesome-all.min.css?1724869793" rel="stylesheet" media="print" onload="this.media='all';this.onload=null;"><noscript><link href="/Datasync/css/fontawesome-all.min.css?1724869793" rel="stylesheet"></noscript>
24-
<link href="/Datasync/css/nucleus.css?1724869793" rel="stylesheet">
25-
<link href="/Datasync/css/auto-complete.css?1724869793" rel="stylesheet" media="print" onload="this.media='all';this.onload=null;"><noscript><link href="/Datasync/css/auto-complete.css?1724869793" rel="stylesheet"></noscript>
26-
<link href="/Datasync/css/perfect-scrollbar.min.css?1724869793" rel="stylesheet">
27-
<link href="/Datasync/css/fonts.css?1724869793" rel="stylesheet" media="print" onload="this.media='all';this.onload=null;"><noscript><link href="/Datasync/css/fonts.css?1724869793" rel="stylesheet"></noscript>
28-
<link href="/Datasync/css/theme.css?1724869793" rel="stylesheet">
29-
<link href="/Datasync/css/theme-auto.css?1724869793" rel="stylesheet" id="R-variant-style">
30-
<link href="/Datasync/css/chroma-auto.css?1724869793" rel="stylesheet" id="R-variant-chroma-style">
31-
<link href="/Datasync/css/variant.css?1724869793" rel="stylesheet">
32-
<link href="/Datasync/css/print.css?1724869793" rel="stylesheet" media="print">
33-
<script src="/Datasync/js/variant.js?1724869793"></script>
23+
<link href="/Datasync/css/fontawesome-all.min.css?1725059400" rel="stylesheet" media="print" onload="this.media='all';this.onload=null;"><noscript><link href="/Datasync/css/fontawesome-all.min.css?1725059400" rel="stylesheet"></noscript>
24+
<link href="/Datasync/css/nucleus.css?1725059400" rel="stylesheet">
25+
<link href="/Datasync/css/auto-complete.css?1725059400" rel="stylesheet" media="print" onload="this.media='all';this.onload=null;"><noscript><link href="/Datasync/css/auto-complete.css?1725059400" rel="stylesheet"></noscript>
26+
<link href="/Datasync/css/perfect-scrollbar.min.css?1725059400" rel="stylesheet">
27+
<link href="/Datasync/css/fonts.css?1725059400" rel="stylesheet" media="print" onload="this.media='all';this.onload=null;"><noscript><link href="/Datasync/css/fonts.css?1725059400" rel="stylesheet"></noscript>
28+
<link href="/Datasync/css/theme.css?1725059400" rel="stylesheet">
29+
<link href="/Datasync/css/theme-auto.css?1725059400" rel="stylesheet" id="R-variant-style">
30+
<link href="/Datasync/css/chroma-auto.css?1725059400" rel="stylesheet" id="R-variant-chroma-style">
31+
<link href="/Datasync/css/variant.css?1725059400" rel="stylesheet">
32+
<link href="/Datasync/css/print.css?1725059400" rel="stylesheet" media="print">
33+
<script src="/Datasync/js/variant.js?1725059400"></script>
3434
<script>
3535
window.relearn = window.relearn || {};
3636
window.relearn.relBasePath='.';

docs/public/categories/index.html

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,17 @@
2020
<link rel="icon" type="image/png" sizes="32x32" href="/favicon/favicon-32x32.png">
2121
<link rel="icon" type="image/png" sizes="16x16" href="/favicon/favicon-16x16.png">
2222
<link rel="manifest" href="/favicon/site.webmanifest">
23-
<link href="/Datasync/css/fontawesome-all.min.css?1724869793" rel="stylesheet" media="print" onload="this.media='all';this.onload=null;"><noscript><link href="/Datasync/css/fontawesome-all.min.css?1724869793" rel="stylesheet"></noscript>
24-
<link href="/Datasync/css/nucleus.css?1724869793" rel="stylesheet">
25-
<link href="/Datasync/css/auto-complete.css?1724869793" rel="stylesheet" media="print" onload="this.media='all';this.onload=null;"><noscript><link href="/Datasync/css/auto-complete.css?1724869793" rel="stylesheet"></noscript>
26-
<link href="/Datasync/css/perfect-scrollbar.min.css?1724869793" rel="stylesheet">
27-
<link href="/Datasync/css/fonts.css?1724869793" rel="stylesheet" media="print" onload="this.media='all';this.onload=null;"><noscript><link href="/Datasync/css/fonts.css?1724869793" rel="stylesheet"></noscript>
28-
<link href="/Datasync/css/theme.css?1724869793" rel="stylesheet">
29-
<link href="/Datasync/css/theme-auto.css?1724869793" rel="stylesheet" id="R-variant-style">
30-
<link href="/Datasync/css/chroma-auto.css?1724869793" rel="stylesheet" id="R-variant-chroma-style">
31-
<link href="/Datasync/css/variant.css?1724869793" rel="stylesheet">
32-
<link href="/Datasync/css/print.css?1724869793" rel="stylesheet" media="print">
33-
<script src="/Datasync/js/variant.js?1724869793"></script>
23+
<link href="/Datasync/css/fontawesome-all.min.css?1725059400" rel="stylesheet" media="print" onload="this.media='all';this.onload=null;"><noscript><link href="/Datasync/css/fontawesome-all.min.css?1725059400" rel="stylesheet"></noscript>
24+
<link href="/Datasync/css/nucleus.css?1725059400" rel="stylesheet">
25+
<link href="/Datasync/css/auto-complete.css?1725059400" rel="stylesheet" media="print" onload="this.media='all';this.onload=null;"><noscript><link href="/Datasync/css/auto-complete.css?1725059400" rel="stylesheet"></noscript>
26+
<link href="/Datasync/css/perfect-scrollbar.min.css?1725059400" rel="stylesheet">
27+
<link href="/Datasync/css/fonts.css?1725059400" rel="stylesheet" media="print" onload="this.media='all';this.onload=null;"><noscript><link href="/Datasync/css/fonts.css?1725059400" rel="stylesheet"></noscript>
28+
<link href="/Datasync/css/theme.css?1725059400" rel="stylesheet">
29+
<link href="/Datasync/css/theme-auto.css?1725059400" rel="stylesheet" id="R-variant-style">
30+
<link href="/Datasync/css/chroma-auto.css?1725059400" rel="stylesheet" id="R-variant-chroma-style">
31+
<link href="/Datasync/css/variant.css?1725059400" rel="stylesheet">
32+
<link href="/Datasync/css/print.css?1725059400" rel="stylesheet" media="print">
33+
<script src="/Datasync/js/variant.js?1725059400"></script>
3434
<script>
3535
window.relearn = window.relearn || {};
3636
window.relearn.relBasePath='..';
@@ -163,12 +163,12 @@ <h1 id="categories">Categories</h1>
163163
<script>
164164
var contentLangs=['en'];
165165
</script>
166-
<script src="/Datasync/js/auto-complete.js?1724869793" defer></script>
167-
<script src="/Datasync/js/lunr/lunr.min.js?1724869793" defer></script>
168-
<script src="/Datasync/js/lunr/lunr.stemmer.support.min.js?1724869793" defer></script>
169-
<script src="/Datasync/js/lunr/lunr.multi.min.js?1724869793" defer></script>
170-
<script src="/Datasync/js/lunr/lunr.en.min.js?1724869793" defer></script>
171-
<script src="/Datasync/js/search.js?1724869793" defer></script>
166+
<script src="/Datasync/js/auto-complete.js?1725059400" defer></script>
167+
<script src="/Datasync/js/lunr/lunr.min.js?1725059400" defer></script>
168+
<script src="/Datasync/js/lunr/lunr.stemmer.support.min.js?1725059400" defer></script>
169+
<script src="/Datasync/js/lunr/lunr.multi.min.js?1725059400" defer></script>
170+
<script src="/Datasync/js/lunr/lunr.en.min.js?1725059400" defer></script>
171+
<script src="/Datasync/js/search.js?1725059400" defer></script>
172172
</div>
173173
<div id="R-homelinks" class="default-animation homelinks">
174174
<ul>
@@ -185,6 +185,7 @@ <h1 id="categories">Categories</h1>
185185
<li data-nav-id="/Datasync/samples/index.html" class=""><a class="padding" href="/Datasync/samples/index.html">Samples</a><ul id="R-subsections-abc4562a0bcf1570d92f916bb82a8b39" class="morespace collapsible-menu">
186186
<li data-nav-id="/Datasync/samples/server/index.html" class=""><a class="padding" href="/Datasync/samples/server/index.html">Sample Server</a></li>
187187
<li data-nav-id="/Datasync/samples/todoapp/index.html" class="alwaysopen"><a class="padding" href="/Datasync/samples/todoapp/index.html">Todo App</a><ul id="R-subsections-64deac9d85858c681d35e673e0fd3b13" class="morespace collapsible-menu">
188+
<li data-nav-id="/Datasync/samples/todoapp/maui/index.html" class=""><a class="padding" href="/Datasync/samples/todoapp/maui/index.html">MAUI</a></li>
188189
<li data-nav-id="/Datasync/samples/todoapp/winui3/index.html" class=""><a class="padding" href="/Datasync/samples/todoapp/winui3/index.html">WinUI3</a></li>
189190
<li data-nav-id="/Datasync/samples/todoapp/wpf/index.html" class=""><a class="padding" href="/Datasync/samples/todoapp/wpf/index.html">WPF</a></li></ul></li></ul></li>
190191
<li data-nav-id="/Datasync/in-depth/index.html" class=""><a class="padding" href="/Datasync/in-depth/index.html">In-depth</a><ul id="R-subsections-3229b26a09fade6cbffa6d892da9210c" class="morespace collapsible-menu">
@@ -250,8 +251,8 @@ <h1 id="categories">Categories</h1>
250251
</div>
251252
</div>
252253
</aside>
253-
<script src="/Datasync/js/clipboard.min.js?1724869793" defer></script>
254-
<script src="/Datasync/js/perfect-scrollbar.min.js?1724869793" defer></script>
255-
<script src="/Datasync/js/theme.js?1724869793" defer></script>
254+
<script src="/Datasync/js/clipboard.min.js?1725059400" defer></script>
255+
<script src="/Datasync/js/perfect-scrollbar.min.js?1725059400" defer></script>
256+
<script src="/Datasync/js/theme.js?1725059400" defer></script>
256257
</body>
257258
</html>

docs/public/css/chroma-auto.css

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
@import "chroma-relearn-light.css?1724869793" screen and (prefers-color-scheme: light);
2-
@import "chroma-relearn-dark.css?1724869793" screen and (prefers-color-scheme: dark);
1+
@import "chroma-relearn-light.css?1725059400" screen and (prefers-color-scheme: light);
2+
@import "chroma-relearn-dark.css?1725059400" screen and (prefers-color-scheme: dark);

docs/public/css/format-print.css

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
@import "theme-relearn-light.css?1724869793";
2-
@import "chroma-relearn-light.css?1724869793";
1+
@import "theme-relearn-light.css?1725059400";
2+
@import "chroma-relearn-light.css?1725059400";
33

44
#R-sidebar {
55
display: none;

docs/public/css/print.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
@import "format-print.css?1724869793";
1+
@import "format-print.css?1725059400";

docs/public/css/swagger.css

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* Styles to make Swagger-UI fit into our theme */
22

3-
@import "fonts.css?1724869793";
4-
@import "variables.css?1724869793";
3+
@import "fonts.css?1725059400";
4+
@import "variables.css?1725059400";
55

66
body{
77
line-height: 1.574;

docs/public/css/theme-auto.css

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
@import "theme-relearn-light.css?1724869793" screen and (prefers-color-scheme: light);
2-
@import "theme-relearn-dark.css?1724869793" screen and (prefers-color-scheme: dark);
1+
@import "theme-relearn-light.css?1725059400" screen and (prefers-color-scheme: light);
2+
@import "theme-relearn-dark.css?1725059400" screen and (prefers-color-scheme: dark);

docs/public/css/variant.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
@import "variables.css?1724869793";
1+
@import "variables.css?1725059400";
22

33
html {
44
color-scheme: only var(--INTERNAL-BROWSER-theme);

0 commit comments

Comments
 (0)