Skip to content

Commit a1ac1c0

Browse files
committed
docs(XamlNavigation): Add Intro to Xaml Navigation loc DE
1 parent 9e7d627 commit a1ac1c0

File tree

15 files changed

+315
-149
lines changed

15 files changed

+315
-149
lines changed

cSpell.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
{
22
// cSpell configuration file
33
"version": "0.2",
4-
"language": "en",
4+
"language": "en,de",
55
"words": [
66
// Add custom words here
77
"DevTKSS",
8-
"Listboard"
8+
"Listboard",
9+
"Mvux"
910
],
1011
"ignoreWords": [],
1112
"ignorePaths": [
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
---
2+
uid: DevTKSS.Uno.SamplesApps.MvuxGallery.XamlNavigation
3+
---
4+
# Navigieren via Xaml in Uno Apps
5+
6+
Jede Anwendung, die mehr als eine einzige Seite umfasst oder eben nicht vollkommen überladen ist, braucht eine vernünftige "Navigation".
7+
8+
Grundlegend enthält es die gleichen Bausteine wie man es von einer Navigation mittels Landkarte und Co kennt:
9+
10+
- **Eine Sammlung von `ViewMap`'s**, mit der wir dem Navigator mitteilen, welche Seite mit welchen Daten zusammengehört. Das kann ein ViewModel oder auch spezifischen Daten sein, wobei es dann ein `DataViewMap` element zusätzlich wird.
11+
- **Eine hierarchisch aufgebaute `Routes` Sammlung**, mit der wir dem Navigator mitteilen, in welcher Relation die verschiedenen Routen zueinander stehen. Wenn wir keine Relation in dem Sinne haben, dann wäre es eine schlichte flache Liste, aber sagen wir mal, wir wollen eine seitliche Navigationsleiste (hierzu können wir bspw. TabBar oder NavigationView nutzen) haben, dann wird das oberste Element in dem eben diese Navigationssteuerelemente UI technisch definiert sind, zum hierarchisch übergeordneten Element auch in unseren Routes:
12+
13+
```plaintext
14+
- MainPage mit NavigationView
15+
- SecondPage
16+
- ThirdPage
17+
```
18+
19+
## Voraussetzungen erfüllen
20+
21+
Solltet ihr schon eine existierende Uno Anwendung haben, prüft einfach mal in der .csproj Datei, ob ihr in der `UnoFeatures` Sammlung die Elemente `Hosting` und `Navigation` habt und fügt diese hinzu, wenn das nicht bereits der Fall sein sollte.
22+
23+
Des weiteren benötigt eure App.xaml.cs Datei folgende Elemente:
24+
25+
![code-csharp[](../../../src/DevTKSS.Uno.Samples.MvuxGallery/App.xaml.cs?highlight=L19-L23,L96,L110,L113-L115,L124-L130)]
26+
27+
Den Namespace, den wir in einer Xaml-basierten Navigation in einer Uno Anwendung benötigen, ist `Uno.Extensions.Navigation.UI`, meist mit dem xmlns Namespace Identifikator `xmlns:uen=` eurer Seite dann vorzufinden.
28+
<<<<<<< HEAD
29+
30+
<!-- ## Navigation mittels NavigationView und Seiten
31+
32+
[!Video [How-To-Uno-XamlNavigation](../images/How-To-Uno-XamlNavigation.mp4)] -->
33+
=======
34+
<!--
35+
## Navigation mittels NavigationView und Seiten
36+
37+
[!Video [How-To-Uno-XamlNavigation](https://youtube.com/)]
38+
-->
39+
>>>>>>> 51f7212 (chore: update Navigation View Sample with IRouteNotifier)

doc/articles/MvuxGallery/toc.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,6 @@ items:
44
- name: Overview
55
uid: DevTKSS.Uno.SampleApps.MvuxGallery.Overview
66
href: Overview.md
7+
- name: Xaml Navigation
8+
uid: DevTKSS.Uno.SampleApps.MvuxGallery.XamlNavigation
9+
href: How-To-XamlNavigation

src/DevTKSS.Uno.Samples.MvuxGallery/App.xaml.cs

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
using System.Text.Json;
2+
using Microsoft.Extensions.Configuration;
3+
using Microsoft.Extensions.DependencyInjection;
24
using Uno.Resizetizer;
35

46
namespace DevTKSS.Uno.Samples.MvuxGallery;
@@ -64,11 +66,12 @@ protected async override void OnLaunched(LaunchActivatedEventArgs args)
6466
.Section<AppConfig>()
6567

6668
.EmbeddedSource<App>("sampledata")
67-
.Section<CodeSampleOptionsConfiguration>("DashboardSampleConfiguration")
68-
.Section<CodeSampleOptionsConfiguration>("MainSampleConfiguration")
69-
.Section<CodeSampleOptionsConfiguration>("ListboardSampleConfiguration")
70-
.Section<CodeSampleOptionsConfiguration>("CounterSampleConfiguration")
71-
.Section<CodeSampleOptionsConfiguration>("SimpleCardsSampleConfiguration")
69+
.Section<CodeSampleOptionsConfiguration>()
70+
.Section<DashboardCodeSampleOptions>()
71+
.Section<MainCodeSampleOptions>()
72+
.Section<ListboardCodeSampleOptions>()
73+
.Section<SimpleCardsCodeSampleOptions>()
74+
.Section<CounterCodeSampleOptions>()
7275
)
7376
// Enable localization (see appsettings.json for supported languages)
7477
.UseLocalization()
@@ -78,30 +81,32 @@ protected async override void OnLaunched(LaunchActivatedEventArgs args)
7881

7982
.AddSingleton<IGalleryImageService, GalleryImageService>()
8083

81-
.AddOptions<CodeSampleOptionsConfiguration>("ListboardSampleConfiguration").Services
82-
.AddNamedSingleton<ICodeSampleService, CodeSampleService>("ListboardSampleService")
84+
// .AddSingleton<ICodeSampleService<CodeSampleOptionsConfiguration>, CodeSampleService<CodeSampleOptionsConfiguration>>()
8385

84-
.AddOptions<CodeSampleOptionsConfiguration>("SimpleCardsSampleConfiguration").Services.
85-
AddNamedSingleton<ICodeSampleService, CodeSampleService>("SimpleCardsSampleService")
86-
87-
.AddOptions<CodeSampleOptionsConfiguration>("CounterSampleConfiguration").Services
88-
.AddNamedSingleton<ICodeSampleService, CodeSampleService>("CounterSampleService")
89-
90-
.AddOptions<CodeSampleOptionsConfiguration>("MainSampleConfiguration").Services
91-
.AddNamedSingleton<ICodeSampleService, CodeSampleService>("MainSampleService")
92-
93-
.AddOptions<CodeSampleOptionsConfiguration>("DashboardSampleConfiguration").Services
94-
.AddNamedSingleton<ICodeSampleService, CodeSampleService>("DashboardSampleService")
86+
.AddSingleton<ICodeSampleService<MainCodeSampleOptions>, CodeSampleService<MainCodeSampleOptions>>()
87+
.AddSingleton<ICodeSampleService<ListboardCodeSampleOptions>,CodeSampleService<ListboardCodeSampleOptions>>()
88+
.AddSingleton<ICodeSampleService<SimpleCardsCodeSampleOptions>, CodeSampleService<SimpleCardsCodeSampleOptions>>()
89+
.AddSingleton<ICodeSampleService<CounterCodeSampleOptions>, CodeSampleService<CounterCodeSampleOptions>>()
90+
.AddSingleton<ICodeSampleService<DashboardCodeSampleOptions>, CodeSampleService<DashboardCodeSampleOptions>>()
9591
)
9692
.UseNavigation(ReactiveViewModelMappings.ViewModelMappings, RegisterRoutes)
9793
.UseSerialization((context, services) =>
9894
services
9995
.AddJsonTypeInfo(CodeSampleOptionContext.Default.CodeSampleOption)
10096
.AddJsonTypeInfo(CodeSampleOptionsConfigurationContext.Default.CodeSampleOptionsConfiguration)
101-
.AddSingleton(new JsonSerializerOptions { PropertyNameCaseInsensitive = true }))
97+
98+
// Following should get removed when NamedOptions can be used with DI Services and really getting values from the configuration
99+
.AddJsonTypeInfo(MainCodeSampleOptionsContext.Default.MainCodeSampleOptions)
100+
.AddJsonTypeInfo(ListboardCodeSampleOptionsContext.Default.ListboardCodeSampleOptions)
101+
.AddJsonTypeInfo(SimpleCardsCodeSampleOptionsContext.Default.SimpleCardsCodeSampleOptions)
102+
.AddJsonTypeInfo(CounterCodeSampleOptionsContext.Default.CounterCodeSampleOptions)
103+
.AddJsonTypeInfo(DashboardCodeSampleOptionsContext.Default.DashboardCodeSampleOptions)
104+
105+
.AddSingleton(new JsonSerializerOptions { PropertyNameCaseInsensitive = true })
106+
)
102107
);
103108
MainWindow = builder.Window;
104-
109+
105110
#if DEBUG
106111
MainWindow.UseStudio();
107112
#endif
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
using Uno.Extensions.Reactive.Commands;
2+
3+
namespace DevTKSS.Uno.Samples.MvuxGallery.Presentation.ViewModels;
4+
public partial record MainModel
5+
{
6+
private readonly INavigator _navigator;
7+
private readonly ILocalizationService _localizationService;
8+
private readonly IStringLocalizer _stringLocalizer;
9+
private readonly IRouteNotifier _routeNotifier;
10+
private readonly ILogger _logger;
11+
public MainModel(
12+
ILocalizationService localizationService,
13+
IStringLocalizer stringLocalizer,
14+
INavigator navigator,
15+
IRouteNotifier routeNotifier,
16+
ILogger<MainModel> logger)
17+
{
18+
_logger = logger;
19+
_routeNotifier = routeNotifier;
20+
_navigator = navigator;
21+
_localizationService = localizationService;
22+
_stringLocalizer = stringLocalizer;
23+
_routeNotifier.RouteChanged += routeNotifier_RouteChanged;
24+
25+
}
26+
27+
public IState<string> CurrentNotifierRoute => State<string>.Value(this, () => string.Empty)
28+
.ForEach(UpdateCurrentHeaderAsync);
29+
private async void routeNotifier_RouteChanged(object? sender, RouteChangedEventArgs e)
30+
{
31+
var RouteName = e.Navigator?.Route?.ToString() ?? string.Empty;
32+
_logger.LogDebug("Route was: {RouteAsString}", RouteName);
33+
await this.CurrentNotifierRoute.SetAsync(RouteName);
34+
}
35+
36+
public IState<string> CurrentHeader => State<string>.Value(this, () => string.Empty);
37+
38+
public ValueTask UpdateCurrentHeaderAsync([FeedParameter(nameof(CurrentNotifierRoute))] string? currentNotifierRoute, CancellationToken ct = default)
39+
{
40+
_logger.LogDebug("CurrentNotifierRoute was: {CurrentNotifierRoute}", currentNotifierRoute);
41+
string newHeader = _stringLocalizer["WelcomeGreeting"];
42+
if (!string.IsNullOrWhiteSpace(currentNotifierRoute))
43+
{
44+
newHeader = _stringLocalizer[currentNotifierRoute + "Title"];
45+
}
46+
return this.CurrentHeader.SetAsync(newHeader);
47+
}
48+
}
49+

src/DevTKSS.Uno.Samples.MvuxGallery/Assets/Samples/NavigationView-Sample.xaml.txt

Lines changed: 19 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
xmlns:local="using:DevTKSS.Uno.Samples.MvuxGallery.Presentation.Views"
55
xmlns:uen="using:Uno.Extensions.Navigation.UI"
66
xmlns:utu="using:Uno.Toolkit.UI"
7+
xmlns:models="using:DevTKSS.Uno.Samples.MvuxGallery.Models"
78
xmlns:um="using:Uno.Material"
89
xmlns:ctk="using:CommunityToolkit.WinUI.Converters"
910
uen:Region.Name="Main"
@@ -12,39 +13,22 @@
1213

1314
<Page.Resources>
1415
<ctk:BoolNegationConverter x:Name="InvertBoolConv"/>
16+
<Thickness x:Key="NavigationViewHeaderMargin">20,20,20,20</Thickness>
17+
<!--Would expect this to be not needed when setting IsTitleBarAutoPaddingEnabled to false, but that does not do anything, so use this instead.
18+
https://learn.microsoft.com/de-de/windows/apps/design/controls/navigationview#top-whitespace-->
1519
</Page.Resources>
1620
<Grid x:Name="MainContentGrid"
1721
uen:Region.Attached="True">
18-
<Grid.RowDefinitions>
19-
<RowDefinition Height="Auto"/>
20-
<RowDefinition Height="*"/>
21-
</Grid.RowDefinitions>
2222

23-
<utu:NavigationBar x:Name="NavBar"
24-
Grid.Row="0"
25-
HorizontalAlignment="Stretch"
26-
HorizontalContentAlignment="Center"
27-
VerticalContentAlignment="Center"
28-
VerticalAlignment="Top"
29-
Content="{Binding Path=AppTitle, Mode=OneWay}"
30-
MainCommandMode="Action"
31-
Background="{ThemeResource PrimaryContainerBrush}"
32-
Foreground="{ThemeResource OnPrimaryContainerBrush}">
33-
<utu:NavigationBar.MainCommand>
34-
<AppBarButton Icon="GlobalNavigationButton"
35-
Command="{x:Bind NavView.IsPaneOpen, Converter={StaticResource InvertBoolConv}}"
36-
Width="{x:Bind NavView.CompactPaneLength, Mode=OneWay}"
37-
HorizontalContentAlignment="Center"/>
38-
</utu:NavigationBar.MainCommand>
39-
</utu:NavigationBar>
40-
41-
<NavigationView x:Name="NavView"
42-
IsBackButtonVisible="Collapsed"
23+
<NavigationView IsBackButtonVisible="Collapsed"
24+
IsTitleBarAutoPaddingEnabled="True"
4325
IsPaneToggleButtonVisible="False"
44-
Grid.Row="1"
45-
PaneDisplayMode="LeftCompact"
26+
27+
PaneDisplayMode="Auto"
4628
uen:Region.Attached="True"
47-
HorizontalAlignment="Stretch">
29+
HorizontalAlignment="Stretch"
30+
Header="{Binding CurrentHeader}">
31+
4832
<NavigationView.MenuItems>
4933
<NavigationViewItem x:Name="NavItemDashboard"
5034
Content="Home"
@@ -54,22 +38,25 @@
5438
Content="Counter"
5539
Icon="Calculator"
5640
uen:Region.Name="Counter" />
57-
41+
5842
<NavigationViewItem Content="List View"
5943
uen:Region.Name="Listboard"
6044
Icon="List" />
45+
6146
<NavigationViewItem Content="Let's play Cards!"
62-
uen:Region.Name="SimpleCards"
63-
Icon="Page" />
47+
uen:Region.Name="SimpleCards">
48+
<NavigationViewItem.Icon>
49+
<FontIcon x:Name="TaskView" Glyph="&#xEB91;" />
50+
</NavigationViewItem.Icon>
51+
</NavigationViewItem>
6452
</NavigationView.MenuItems>
6553

6654
<NavigationView.Content>
6755
<Grid x:Name="NavigationViewContentGrid"
6856
uen:Region.Attached="True"
6957
uen:Region.Navigator="Visibility"
70-
Visibility="Visible"/>
58+
Visibility="Visible" />
7159
</NavigationView.Content>
7260
</NavigationView>
7361
</Grid>
74-
7562
</Page>

src/DevTKSS.Uno.Samples.MvuxGallery/Models/CodeSamples/CodeSampleOptionsConfiguration.cs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,47 @@ public record CodeSampleOptionsConfiguration()
88
public partial class CodeSampleOptionsConfigurationContext : JsonSerializerContext
99
{
1010
}
11+
12+
public record ListboardCodeSampleOptions : CodeSampleOptionsConfiguration
13+
{
14+
}
15+
16+
[JsonSerializable(typeof(ListboardCodeSampleOptions))]
17+
public partial class ListboardCodeSampleOptionsContext : JsonSerializerContext
18+
{
19+
}
20+
21+
public record MainCodeSampleOptions : CodeSampleOptionsConfiguration
22+
{
23+
}
24+
25+
[JsonSerializable(typeof(MainCodeSampleOptions))]
26+
public partial class MainCodeSampleOptionsContext : JsonSerializerContext
27+
{
28+
}
29+
30+
public record CounterCodeSampleOptions : CodeSampleOptionsConfiguration
31+
{
32+
}
33+
34+
[JsonSerializable(typeof(CounterCodeSampleOptions))]
35+
public partial class CounterCodeSampleOptionsContext : JsonSerializerContext
36+
{
37+
}
38+
39+
public record SimpleCardsCodeSampleOptions : CodeSampleOptionsConfiguration
40+
{
41+
}
42+
[JsonSerializable(typeof(SimpleCardsCodeSampleOptions))]
43+
public partial class SimpleCardsCodeSampleOptionsContext : JsonSerializerContext
44+
{
45+
}
46+
47+
public record DashboardCodeSampleOptions : CodeSampleOptionsConfiguration
48+
{
49+
}
50+
51+
[JsonSerializable(typeof(DashboardCodeSampleOptions))]
52+
public partial class DashboardCodeSampleOptionsContext : JsonSerializerContext
53+
{
54+
}

src/DevTKSS.Uno.Samples.MvuxGallery/Models/CodeSamples/CodeSampleService.cs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,23 @@
11
using Microsoft.Extensions.Configuration;
22

33
namespace DevTKSS.Uno.Samples.MvuxGallery.Models.CodeSamples;
4-
public record CodeSampleService : ICodeSampleService
4+
public record CodeSampleService<SampleOptions> : ICodeSampleService<SampleOptions>
5+
where SampleOptions : CodeSampleOptionsConfiguration
56
{
67
public CodeSampleService(
7-
IOptions<CodeSampleOptionsConfiguration> options,
8-
ILogger<CodeSampleService> logger,
8+
IOptions<SampleOptions> options,
9+
ILogger<CodeSampleService<SampleOptions>> logger,
910
IStorage storage)
1011
{
1112
_options = options.Value;
13+
1214
_logger = logger;
1315
_storage = storage;
1416
}
1517

1618
private readonly IStorage _storage;
17-
private readonly ILogger<CodeSampleService> _logger;
18-
private readonly CodeSampleOptionsConfiguration _options;
19+
private readonly ILogger<CodeSampleService<SampleOptions>> _logger;
20+
private readonly SampleOptions _options;
1921

2022
/// <summary>
2123
/// Get a static Collection of Values for <see cref="CodeSampleOptions"/>
@@ -34,7 +36,7 @@ public CodeSampleService(
3436
public async ValueTask<IImmutableList<string>> GetCodeSampleOptionsAsync(CancellationToken ct = default)
3537
{
3638
await Task.Delay(1);
37-
_logger.LogInformation("Options: {options}", _options.Samples.Keys.ToString());
39+
_logger.LogInformation("Options: {options}", _options.Samples);
3840
return _options.Samples.Keys.ToImmutableList();
3941
}
4042

src/DevTKSS.Uno.Samples.MvuxGallery/Models/CodeSamples/ICodeSampleService.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
namespace DevTKSS.Uno.Samples.MvuxGallery.Models.CodeSamples;
33

4-
public interface ICodeSampleService
4+
public interface ICodeSampleService<SampleOptions> where SampleOptions : class
55
{
66
/// <summary>
77
/// Get the content of a specific code sample asynchronously.

0 commit comments

Comments
 (0)