Skip to content

Commit 2e9707c

Browse files
Enhance maui-mobile developer sample with recent updates (#31151)
* sample port * changes * template changes * Update MauiApp.1.csproj * Update Styles.xaml * added singleton * Update SemanticScreenReaderAsyncImplementation.cs * - exclude extra files * - increment previous * Removed AndExpand * - fix data type * Changes for warning * Update CategoryChart.xaml * cleared warning --------- Co-authored-by: Shane Neuville <[email protected]> Co-authored-by: Shane Neuville <[email protected]>
1 parent 136e6c7 commit 2e9707c

File tree

21 files changed

+300
-71
lines changed

21 files changed

+300
-71
lines changed

src/Templates/build.ps1

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ param (
66
[Parameter(Mandatory=$false, HelpMessage="Specify the path to the template project to build")]
77
[string]$templatesProjectPath = "src\Microsoft.Maui.Templates.csproj",
88
[Parameter(Mandatory=$false, HelpMessage="Specify whether to start Visual Studio (Code) after creating the new project with the latest template changes")]
9-
[bool]$startVsAfterBuild = $true
9+
[bool]$startVsAfterBuild = $true,
10+
[Parameter(Mandatory=$false, HelpMessage="Additional arguments to pass to the dotnet new command (e.g., '--sample-content')")]
11+
[string]$additionalProjectArgs = ""
1012
)
1113

1214
# Source the utils script for some common functionalities
@@ -39,7 +41,11 @@ Empty-UserHomeTemplateEngineFolder
3941
dotnet new install $nupkgPath.FullName
4042

4143
# Create a new dotnet project using the specified project type
42-
dotnet new $projectType -o ./.tempTemplateOutput/NewProject --force
44+
if ($additionalProjectArgs) {
45+
dotnet new $projectType $additionalProjectArgs -o ./.tempTemplateOutput/NewProject --force
46+
} else {
47+
dotnet new $projectType -o ./.tempTemplateOutput/NewProject --force
48+
}
4349

4450
if ($startVsAfterBuild -eq $false) {
4551
exit 0

src/Templates/src/templates/maui-mobile/.template.config/template.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
{
6161
"condition": "(!IncludeSampleContent)",
6262
"exclude": [
63+
"Converter/**",
6364
"Data/**",
6465
"GlobalUsings.cs",
6566
"Messages/**",
@@ -72,7 +73,8 @@
7273
"Resources/Fonts/FluentUI.cs",
7374
"Services/**",
7475
"Resources/Styles/AppStyles.xaml",
75-
"Utilities/**"
76+
"Utilities/**",
77+
"Platforms/iOS/SemanticScreenReaderAsyncImplementation.cs"
7678
]
7779
},
7880
{

src/Templates/src/templates/maui-mobile/App.xaml.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
namespace MauiApp._1;
1+
using Microsoft.Extensions.DependencyInjection;
2+
3+
namespace MauiApp._1;
24

35
public partial class App : Application
46
{
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
using System.Globalization;
2+
using Microsoft.Maui.Controls;
3+
using MauiApp._1.Models;
4+
5+
namespace MauiApp._1.Converter;
6+
7+
public class DataLabelValueConverter : IValueConverter
8+
{
9+
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
10+
{
11+
if (value is CategoryChartData categoryChartData)
12+
{
13+
switch (parameter?.ToString())
14+
{
15+
case "Title":
16+
return categoryChartData.Title;
17+
18+
case "Count":
19+
return categoryChartData.Count;
20+
}
21+
}
22+
23+
return value;
24+
}
25+
26+
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
27+
{
28+
return value;
29+
}
30+
}

src/Templates/src/templates/maui-mobile/MauiProgram.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ public static MauiApp CreateMauiApp()
5050
builder.Services.AddSingleton<MainPageModel>();
5151
builder.Services.AddSingleton<ProjectListPageModel>();
5252
builder.Services.AddSingleton<ManageMetaPageModel>();
53+
#if IOS
54+
builder.Services.AddSingleton<IAsyncAnnouncement, SemanticScreenReaderAsyncImplementation>();
55+
#endif
5356

5457
builder.Services.AddTransientWithShellRoute<ProjectDetailPage, ProjectDetailPageModel>("project");
5558
builder.Services.AddTransientWithShellRoute<TaskDetailPage, TaskDetailPageModel>("task");

src/Templates/src/templates/maui-mobile/Models/Project.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,12 @@ public class Project
1818

1919
public List<Tag> Tags { get; set; } = [];
2020

21-
public override string ToString() => $"{Name}";
21+
public string AccessibilityDescription
22+
{
23+
get { return $"{Name} Project. {Description}"; }
24+
}
25+
26+
public override string ToString() => $"{Name}";
2227
}
2328

2429
public class ProjectsJson

src/Templates/src/templates/maui-mobile/PageModels/ManageMetaPageModel.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ private async Task SaveCategories()
4747
}
4848

4949
await AppShell.DisplayToastAsync("Categories saved");
50+
await AnnouncementHelper.Announce("Categories saved");
5051
}
5152

5253
[RelayCommand]
@@ -55,6 +56,7 @@ private async Task DeleteCategory(Category category)
5556
Categories.Remove(category);
5657
await _categoryRepository.DeleteItemAsync(category);
5758
await AppShell.DisplayToastAsync("Category deleted");
59+
await AnnouncementHelper.Announce("Category deleted");
5860
}
5961

6062
[RelayCommand]
@@ -64,6 +66,7 @@ private async Task AddCategory()
6466
Categories.Add(category);
6567
await _categoryRepository.SaveItemAsync(category);
6668
await AppShell.DisplayToastAsync("Category added");
69+
await AnnouncementHelper.Announce("Category added");
6770
}
6871

6972
[RelayCommand]
@@ -75,6 +78,7 @@ private async Task SaveTags()
7578
}
7679

7780
await AppShell.DisplayToastAsync("Tags saved");
81+
await AnnouncementHelper.Announce("Tags saved");
7882
}
7983

8084
[RelayCommand]
@@ -83,6 +87,7 @@ private async Task DeleteTag(Tag tag)
8387
Tags.Remove(tag);
8488
await _tagRepository.DeleteItemAsync(tag);
8589
await AppShell.DisplayToastAsync("Tag deleted");
90+
await AnnouncementHelper.Announce("Tags deleted");
8691
}
8792

8893
[RelayCommand]
@@ -92,6 +97,7 @@ private async Task AddTag()
9297
Tags.Add(tag);
9398
await _tagRepository.SaveItemAsync(tag);
9499
await AppShell.DisplayToastAsync("Tag added");
100+
await AnnouncementHelper.Announce("Tags added");
95101
}
96102

97103
[RelayCommand]
@@ -102,4 +108,4 @@ private async Task Reset()
102108
Preferences.Default.Set("is_seeded", true);
103109
await Shell.Current.GoToAsync("//main");
104110
}
105-
}
111+
}

src/Templates/src/templates/maui-mobile/PageModels/ProjectDetailPageModel.cs

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,19 @@ public partial class ProjectDetailPageModel : ObservableObject, IQueryAttributab
5252
new IconData { Icon = FluentUI.bot_24_regular, Description = "Bot Icon" }
5353
};
5454

55-
public bool HasCompletedTasks
55+
private bool _canDelete;
56+
57+
public bool CanDelete
58+
{
59+
get => _canDelete;
60+
set
61+
{
62+
_canDelete = value;
63+
DeleteCommand.NotifyCanExecuteChanged();
64+
}
65+
}
66+
67+
public bool HasCompletedTasks
5668
=> _project?.Tasks.Any(t => t.IsCompleted) ?? false;
5769

5870
public ProjectDetailPageModel(ProjectRepository projectRepository, TaskRepository taskRepository, CategoryRepository categoryRepository, TagRepository tagRepository, ModalErrorHandler errorHandler)
@@ -145,7 +157,8 @@ private async Task LoadData(int id)
145157
finally
146158
{
147159
IsBusy = false;
148-
OnPropertyChanged(nameof(HasCompletedTasks));
160+
CanDelete = !_project.IsNullOrNew();
161+
OnPropertyChanged(nameof(HasCompletedTasks));
149162
}
150163
}
151164

@@ -217,7 +230,7 @@ await Shell.Current.GoToAsync($"task",
217230
});
218231
}
219232

220-
[RelayCommand]
233+
[RelayCommand(CanExecute = nameof(CanDelete))]
221234
private async Task Delete()
222235
{
223236
if (_project.IsNullOrNew())
@@ -245,14 +258,26 @@ private async Task ToggleTag(Tag tag)
245258
if (tag.IsSelected)
246259
{
247260
await _tagRepository.SaveItemAsync(tag, _project.ID);
261+
AllTags = new(AllTags);
262+
await AnnouncementHelper.Announce($"{tag.Title} selected");
248263
}
249264
else
250265
{
251266
await _tagRepository.DeleteItemAsync(tag, _project.ID);
267+
AllTags = new(AllTags);
268+
await AnnouncementHelper.Announce($"{tag.Title} unselected");
252269
}
253270
}
271+
else
272+
{
273+
AllTags = new(AllTags);
274+
}
275+
}
254276

255-
AllTags = new(AllTags);
277+
[RelayCommand]
278+
private async Task IconSelected(IconData icon)
279+
{
280+
await AnnouncementHelper.Announce($"{icon.Description} selected");
256281
}
257282

258283
[RelayCommand]

src/Templates/src/templates/maui-mobile/Pages/Controls/CategoryChart.xaml

Lines changed: 55 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,46 +5,77 @@
55
xmlns:controls="clr-namespace:MauiApp._1.Pages.Controls"
66
xmlns:shimmer="clr-namespace:Syncfusion.Maui.Toolkit.Shimmer;assembly=Syncfusion.Maui.Toolkit"
77
xmlns:pageModels="clr-namespace:MauiApp._1.PageModels"
8+
xmlns:models="clr-namespace:MauiApp._1.Models"
9+
xmlns:converter="clr-namespace:MauiApp._1.Converter"
810
x:Class="MauiApp._1.Pages.Controls.CategoryChart"
11+
x:DataType="pageModels:MainPageModel"
912
HeightRequest="{OnIdiom 300, Phone=200}"
1013
Margin="0, 12"
11-
Style="{StaticResource CardStyle}"
12-
x:DataType="pageModels:MainPageModel">
14+
Style="{StaticResource CardStyle}">
1315
<shimmer:SfShimmer
16+
AutomationProperties.IsInAccessibleTree="False"
1417
BackgroundColor="Transparent"
15-
VerticalOptions="FillAndExpand"
16-
IsActive ="{Binding IsBusy}">
18+
VerticalOptions="Fill"
19+
x:DataType="pageModels:MainPageModel"
20+
IsActive="{Binding IsBusy}">
1721
<shimmer:SfShimmer.CustomView>
1822
<Grid>
19-
<BoxView
23+
<BoxView
2024
CornerRadius="12"
21-
VerticalOptions="FillAndExpand"
25+
VerticalOptions="Fill"
2226
Style="{StaticResource ShimmerCustomViewStyle}"/>
2327
</Grid>
2428
</shimmer:SfShimmer.CustomView>
2529
<shimmer:SfShimmer.Content>
26-
<chart:SfCircularChart x:Name="Chart">
27-
<chart:SfCircularChart.Legend>
28-
<controls:LegendExt Placement="Right">
29-
<chart:ChartLegend.LabelStyle>
30-
<chart:ChartLegendLabelStyle
31-
TextColor="{AppThemeBinding
32-
Light={StaticResource DarkOnLightBackground},
33-
Dark={StaticResource LightOnDarkBackground}}"
34-
Margin="5"
35-
FontSize="18" />
36-
</chart:ChartLegend.LabelStyle>
37-
</controls:LegendExt>
38-
</chart:SfCircularChart.Legend>
39-
<chart:RadialBarSeries
30+
<chart:SfCircularChart x:Name="Chart"
31+
SemanticProperties.Description="Task Categories Chart">
32+
<chart:SfCircularChart.Resources>
33+
<converter:DataLabelValueConverter x:Key="valueConverter"/>
34+
</chart:SfCircularChart.Resources>
35+
<chart:DoughnutSeries
36+
x:DataType="pageModels:MainPageModel"
4037
ItemsSource="{Binding TodoCategoryData}"
4138
PaletteBrushes="{Binding TodoCategoryColors}"
4239
XBindingPath="Title"
43-
YBindingPath="Count"
40+
YBindingPath="Count"
4441
ShowDataLabels="True"
45-
EnableTooltip="True"
46-
TrackFill="{AppThemeBinding Light={StaticResource LightBackground}, Dark={StaticResource DarkBackground}}"
47-
CapStyle = "BothCurve"/>
42+
EnableTooltip="False"
43+
x:Name="doughnutSeries"
44+
Radius="{OnIdiom 0.6, Phone=0.5}"
45+
InnerRadius="0.7">
46+
<chart:DoughnutSeries.LabelTemplate>
47+
<DataTemplate>
48+
<HorizontalStackLayout x:DataType="chart:ChartDataLabel">
49+
<Label Text="{Binding Item, Converter={StaticResource valueConverter}, ConverterParameter='Title'}"
50+
TextColor="{AppThemeBinding
51+
Light={StaticResource DarkOnLightBackground},
52+
Dark={StaticResource LightOnDarkBackground}}"
53+
FontSize="{OnIdiom 18, Phone=14}"/>
54+
<Label Text=": "
55+
TextColor="{AppThemeBinding
56+
Light={StaticResource DarkOnLightBackground},
57+
Dark={StaticResource LightOnDarkBackground}}"
58+
FontSize="{OnIdiom 18, Phone=14}"/>
59+
<Label Text="{Binding Item, Converter={StaticResource valueConverter}, ConverterParameter='Count'}"
60+
TextColor="{AppThemeBinding
61+
Light={StaticResource DarkOnLightBackground},
62+
Dark={StaticResource LightOnDarkBackground}}"
63+
FontSize="{OnIdiom 18, Phone=14}"/>
64+
</HorizontalStackLayout>
65+
</DataTemplate>
66+
</chart:DoughnutSeries.LabelTemplate>
67+
68+
<chart:DoughnutSeries.DataLabelSettings>
69+
<chart:CircularDataLabelSettings LabelPosition="Outside"
70+
SmartLabelAlignment="Shift">
71+
<chart:CircularDataLabelSettings.ConnectorLineSettings>
72+
<chart:ConnectorLineStyle ConnectorType="Line"
73+
StrokeWidth="3"></chart:ConnectorLineStyle>
74+
</chart:CircularDataLabelSettings.ConnectorLineSettings>
75+
</chart:CircularDataLabelSettings>
76+
</chart:DoughnutSeries.DataLabelSettings>
77+
</chart:DoughnutSeries>
78+
4879
</chart:SfCircularChart>
4980
</shimmer:SfShimmer.Content>
5081
</shimmer:SfShimmer>

src/Templates/src/templates/maui-mobile/Pages/Controls/ProjectCardView.xaml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@
77
xmlns:pageModels="clr-namespace:MauiApp._1.PageModels"
88
xmlns:shimmer="clr-namespace:Syncfusion.Maui.Toolkit.Shimmer;assembly=Syncfusion.Maui.Toolkit"
99
x:Class="MauiApp._1.Pages.Controls.ProjectCardView"
10+
SemanticProperties.Description="{Binding AccessibilityDescription}"
1011
Style="{StaticResource CardStyle}"
1112
x:DataType="models:Project">
1213
<shimmer:SfShimmer
1314
BackgroundColor="Transparent"
14-
VerticalOptions="FillAndExpand"
15+
VerticalOptions="Fill"
1516
IsActive="{Binding IsBusy, Source={RelativeSource AncestorType={x:Type pageModels:MainPageModel}}, x:DataType=pageModels:IProjectTaskPageModel}">
1617
<shimmer:SfShimmer.CustomView>
1718
<VerticalStackLayout Spacing="15">
@@ -45,7 +46,7 @@
4546
Size="{StaticResource IconSize}"/>
4647
</Image.Source>
4748
</Image>
48-
<Label Text="{Binding Name}" TextColor="{StaticResource Gray400}" FontSize="14" TextTransform="Uppercase"/>
49+
<Label Text="{Binding Name}" TextColor="{AppThemeBinding Light={StaticResource Gray600}, Dark={StaticResource Gray400}}" FontSize="14" TextTransform="Uppercase"/>
4950
<Label Text="{Binding Description}" LineBreakMode="WordWrap"/>
5051
<HorizontalStackLayout Spacing="15" BindableLayout.ItemsSource="{Binding Tags}">
5152
<BindableLayout.ItemTemplate>

0 commit comments

Comments
 (0)