Skip to content

Commit 40a7784

Browse files
committed
Merge remote-tracking branch 'origin/141-propertysetterscontextextension-binding-multibinding-and-dynamicresource-support' into develop
2 parents 9308667 + 9b619ce commit 40a7784

File tree

9 files changed

+382
-105
lines changed

9 files changed

+382
-105
lines changed

README.md

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1101,6 +1101,20 @@ public class NumericValidationTriggerAction : TriggerAction<Entry>
11011101
}
11021102
```
11031103

1104+
And here is the definition of the `NumericValidationTriggerAction` class:
1105+
1106+
```csharp
1107+
public class NumericValidationTriggerAction : TriggerAction<Entry>
1108+
{
1109+
protected override void Invoke(Entry entry)
1110+
{
1111+
double result;
1112+
bool isValid = Double.TryParse(entry.Text, out result);
1113+
entry.TextColor = isValid ? Colors.Black : Colors.Red;
1114+
}
1115+
}
1116+
```
1117+
11041118
# .NET built-in Hot-Reload
11051119

11061120
Additionally, the FmgLib.MauiMarkup library includes hot reload support to make the development process faster and more efficient.
@@ -1134,20 +1148,6 @@ public partial class ExamplePage : ContentPage, IFmgLibHotReload
11341148
}
11351149
```
11361150

1137-
And here is the definition of the `NumericValidationTriggerAction` class:
1138-
1139-
```csharp
1140-
public class NumericValidationTriggerAction : TriggerAction<Entry>
1141-
{
1142-
protected override void Invoke(Entry entry)
1143-
{
1144-
double result;
1145-
bool isValid = Double.TryParse(entry.Text, out result);
1146-
entry.TextColor = isValid ? Colors.Black : Colors.Red;
1147-
}
1148-
}
1149-
```
1150-
11511151
# Extensions for 3rd Party Controls
11521152

11531153
FmgLib.MauiMarkup library can also generate extension methods for controls from third-party libraries. To achieve this, you should utilize the `MauiMarkupAttribute` provided by FmgLib.MauiMarkup.
Lines changed: 73 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,85 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<Project Sdk="Microsoft.NET.Sdk">
3-
<PropertyGroup>
4-
<TargetFrameworks>net8.0-android</TargetFrameworks>
5-
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('osx'))">$(TargetFrameworks);net8.0-ios;net8.0-maccatalyst</TargetFrameworks>
6-
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net8.0-ios;net8.0-maccatalyst;net8.0-windows10.0.19041.0</TargetFrameworks>
7-
<!-- <TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net8.0-tizen</TargetFrameworks> -->
8-
<TargetFrameworks>$(TargetFrameworks);net8.0</TargetFrameworks>
9-
<OutputType Condition="'$(TargetFramework)' != 'net8.0'">Exe</OutputType>
3+
<PropertyGroup>
4+
<TargetFrameworks>net8.0-android</TargetFrameworks>
5+
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('osx'))">$(TargetFrameworks);net8.0-ios;net8.0-maccatalyst</TargetFrameworks>
6+
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net8.0-ios;net8.0-maccatalyst;net8.0-windows10.0.19041.0</TargetFrameworks>
7+
<!-- <TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net8.0-tizen</TargetFrameworks> -->
8+
<TargetFrameworks>$(TargetFrameworks);net8.0</TargetFrameworks>
9+
<OutputType Condition="'$(TargetFramework)' != 'net8.0'">Exe</OutputType>
1010

11-
<!-- .NET MAUI -->
12-
<UseMaui>true</UseMaui>
13-
<SingleProject>true</SingleProject>
11+
<!-- .NET MAUI -->
12+
<UseMaui>true</UseMaui>
13+
<SingleProject>true</SingleProject>
1414

15-
<!-- Project Options -->
16-
<Nullable>enable</Nullable>
17-
<LangVersion>latest</LangVersion>
18-
<ImplicitUsings>enable</ImplicitUsings>
19-
<RootNamespace>MyOrderApp</RootNamespace>
15+
<!-- Project Options -->
16+
<Nullable>enable</Nullable>
17+
<LangVersion>latest</LangVersion>
18+
<ImplicitUsings>enable</ImplicitUsings>
19+
<RootNamespace>MyOrderApp</RootNamespace>
2020

21-
<!-- Display name -->
22-
<ApplicationTitle>MyOrderApp</ApplicationTitle>
21+
<!-- Display name -->
22+
<ApplicationTitle>MyOrderApp</ApplicationTitle>
2323

24-
<!-- App Identifier -->
25-
<ApplicationId>com.companyname.myorderapp</ApplicationId>
26-
<ApplicationIdGuid>0f1f5ccb-47f5-4b4b-8927-96cc6840eea4</ApplicationIdGuid>
24+
<!-- App Identifier -->
25+
<ApplicationId>com.companyname.myorderapp</ApplicationId>
26+
<ApplicationIdGuid>0f1f5ccb-47f5-4b4b-8927-96cc6840eea4</ApplicationIdGuid>
2727

28-
<!-- Versions -->
29-
<ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>
30-
<ApplicationVersion>1</ApplicationVersion>
28+
<!-- Versions -->
29+
<ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>
30+
<ApplicationVersion>1</ApplicationVersion>
3131

32-
<!-- Target Platform Options -->
33-
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">14.2</SupportedOSPlatformVersion>
34-
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">14.0</SupportedOSPlatformVersion>
35-
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">21.0</SupportedOSPlatformVersion>
36-
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'tizen'">6.5</SupportedOSPlatformVersion>
37-
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</SupportedOSPlatformVersion>
32+
<!-- Target Platform Options -->
33+
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">14.2</SupportedOSPlatformVersion>
34+
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">14.0</SupportedOSPlatformVersion>
35+
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">21.0</SupportedOSPlatformVersion>
36+
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'tizen'">6.5</SupportedOSPlatformVersion>
37+
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</SupportedOSPlatformVersion>
3838

39-
<!-- Minimum Target OS Version for Windows Platform -->
40-
<TargetPlatformMinVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</TargetPlatformMinVersion>
41-
</PropertyGroup>
39+
<!-- Minimum Target OS Version for Windows Platform -->
40+
<TargetPlatformMinVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</TargetPlatformMinVersion>
41+
</PropertyGroup>
4242

43-
<ItemGroup>
44-
<!-- App Icon -->
45-
<MauiIcon Include="Resources\appicon.svg" ForegroundFile="Resources\appiconfg.svg" Color="#512BD4" />
46-
<!-- Splash Screen -->
47-
<MauiSplashScreen Include="Resources\appiconfg.svg" Color="#512BD4" BaseSize="128,128" />
48-
<!-- Images -->
49-
<MauiImage Include="Resources\Images\*" />
50-
<MauiImage Update="Resources\Images\dotnet_bot.svg" BaseSize="168,208" />
51-
<!-- Custom Fonts -->
52-
<MauiFont Include="Resources\Fonts\*" />
53-
<!-- Raw Assets (also remove the "Resources\Raw" prefix) -->
54-
<MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
55-
</ItemGroup>
43+
<ItemGroup>
44+
<!-- App Icon -->
45+
<MauiIcon Include="Resources\appicon.svg" ForegroundFile="Resources\appiconfg.svg" Color="#512BD4" />
46+
<!-- Splash Screen -->
47+
<MauiSplashScreen Include="Resources\appiconfg.svg" Color="#512BD4" BaseSize="128,128" />
48+
<!-- Images -->
49+
<MauiImage Include="Resources\Images\*" />
50+
<MauiImage Update="Resources\Images\dotnet_bot.svg" BaseSize="168,208" />
51+
<!-- Custom Fonts -->
52+
<MauiFont Include="Resources\Fonts\*" />
53+
<!-- Raw Assets (also remove the "Resources\Raw" prefix) -->
54+
<MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
55+
</ItemGroup>
5656

57-
<ItemGroup>
58-
<None Remove="MyOrderApp.code-workspace" />
59-
<None Remove="Resources\Images\background.jpg" />
60-
<None Remove="Resources\Images\basket.png" />
61-
<None Remove="Resources\Images\categories.png" />
62-
<None Remove="Resources\Images\chevron.png" />
63-
<None Remove="Resources\Images\favorite.png" />
64-
<None Remove="Resources\Images\favorites.png" />
65-
<None Remove="Resources\Images\home.png" />
66-
<None Remove="Resources\Images\not_favorite.png" />
67-
<None Remove="Resources\Images\products.png" />
68-
<None Remove="Resources\Images\remove.png" />
69-
<None Remove="Resources\Images\white_bread.png" />
70-
<None Remove="Resources\Raw\completed.json" />
71-
</ItemGroup>
72-
73-
<ItemGroup>
74-
<PackageReference Include="AutoMapper" Version="13.0.1" />
75-
<PackageReference Include="FmgLib.MauiMarkup" Version="8.8.1" />
76-
<PackageReference Include="LiteDB" Version="5.0.20" />
77-
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="8.*" Condition="'$(Configuration)' == 'Debug'" />
78-
<PackageReference Include="Microsoft.Maui.Controls" Version="8.0.40" />
79-
<PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="8.0.40" />
80-
<PackageReference Include="CommunityToolkit.Maui" Version="9.0.1" />
81-
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
82-
<PackageReference Include="SkiaSharp.Extended.UI.Maui" Version="2.0.0" />
83-
</ItemGroup>
57+
<ItemGroup>
58+
<None Remove="MyOrderApp.code-workspace" />
59+
<None Remove="Resources\Images\background.jpg" />
60+
<None Remove="Resources\Images\basket.png" />
61+
<None Remove="Resources\Images\categories.png" />
62+
<None Remove="Resources\Images\chevron.png" />
63+
<None Remove="Resources\Images\favorite.png" />
64+
<None Remove="Resources\Images\favorites.png" />
65+
<None Remove="Resources\Images\home.png" />
66+
<None Remove="Resources\Images\not_favorite.png" />
67+
<None Remove="Resources\Images\products.png" />
68+
<None Remove="Resources\Images\remove.png" />
69+
<None Remove="Resources\Images\white_bread.png" />
70+
<None Remove="Resources\Raw\completed.json" />
71+
</ItemGroup>
72+
<ItemGroup>
73+
<ProjectReference Include="..\..\src\FmgLib.MauiMarkup\FmgLib.MauiMarkup.csproj" />
74+
</ItemGroup>
75+
<ItemGroup>
76+
<PackageReference Include="AutoMapper" Version="13.0.1" />
77+
<PackageReference Include="LiteDB" Version="5.0.20" />
78+
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="8.*" Condition="'$(Configuration)' == 'Debug'" />
79+
<PackageReference Include="Microsoft.Maui.Controls" Version="8.0.40" />
80+
<PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="8.0.40" />
81+
<PackageReference Include="CommunityToolkit.Maui" Version="9.0.1" />
82+
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
83+
<PackageReference Include="SkiaSharp.Extended.UI.Maui" Version="2.0.0" />
84+
</ItemGroup>
8485
</Project>

src/FmgLib.MauiMarkup/Core/Builder/PropertyBindingBuilder.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,8 @@ public bool Build()
6161
if (path != null)
6262
{
6363
Context.BindableObject.SetBinding(Context.Property, new Binding(path, bindingMode, converter, converterParameter, stringFormat, source)
64-
{
65-
FallbackValue = fallbackValue,
66-
TargetNullValue = targetNullValue
67-
});
64+
.FallbackValue(fallbackValue)
65+
.TargetNullValue(targetNullValue));
6866
return true;
6967
}
7068

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
using System.Globalization;
2+
3+
namespace FmgLib.MauiMarkup;
4+
5+
public sealed class PropertySettersBindingBuilder<T> : IPropertySettersBuilder<T>
6+
{
7+
public class ValueConverter : IValueConverter
8+
{
9+
internal Func<object, T> ConvertFunction;
10+
11+
internal Func<T, object> ConvertBackFunction;
12+
13+
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
14+
{
15+
if (value != null && ConvertFunction != null)
16+
{
17+
return ConvertFunction(value);
18+
}
19+
20+
return null;
21+
}
22+
23+
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
24+
{
25+
if (value != null && ConvertBackFunction != null)
26+
{
27+
return ConvertBackFunction((T)value);
28+
}
29+
30+
return null;
31+
}
32+
}
33+
34+
private string path;
35+
36+
private BindingMode bindingMode;
37+
38+
private IValueConverter converter;
39+
40+
private ValueConverter valueConverter;
41+
42+
private string converterParameter;
43+
44+
private string stringFormat;
45+
46+
private object source;
47+
48+
private object fallbackValue;
49+
50+
private object targetNullValue;
51+
52+
public PropertySettersContext<T> Context { get; set; }
53+
54+
public PropertySettersBindingBuilder(PropertySettersContext<T> context)
55+
{
56+
Context = context;
57+
}
58+
59+
public bool Build()
60+
{
61+
if (path != null)
62+
{
63+
Context.XamlSetters.Add(
64+
new Setter
65+
{
66+
Property = Context.Property,
67+
Value = new Binding(path, bindingMode, converter, converterParameter, stringFormat, source)
68+
.FallbackValue(fallbackValue)
69+
.TargetNullValue(targetNullValue)
70+
}
71+
);
72+
return true;
73+
}
74+
75+
return false;
76+
}
77+
78+
public PropertySettersBindingBuilder<T> Path(string path)
79+
{
80+
this.path = path;
81+
return this;
82+
}
83+
84+
public PropertySettersBindingBuilder<T> StringFormat(string stringFormat)
85+
{
86+
this.stringFormat = stringFormat;
87+
return this;
88+
}
89+
90+
public PropertySettersBindingBuilder<T> BindingMode(BindingMode bindingMode)
91+
{
92+
this.bindingMode = bindingMode;
93+
return this;
94+
}
95+
96+
public PropertySettersBindingBuilder<T> Converter(IValueConverter converter)
97+
{
98+
this.converter = converter;
99+
return this;
100+
}
101+
102+
public PropertySettersBindingBuilder<T> Parameter(string converterParameter)
103+
{
104+
this.converterParameter = converterParameter;
105+
return this;
106+
}
107+
108+
public PropertySettersBindingBuilder<T> Source(object source)
109+
{
110+
this.source = source;
111+
return this;
112+
}
113+
114+
public PropertySettersBindingBuilder<T> FallbackValue(object fallbackValue)
115+
{
116+
this.fallbackValue = fallbackValue;
117+
return this;
118+
}
119+
120+
public PropertySettersBindingBuilder<T> TargetNullValue(object targetNullValue)
121+
{
122+
this.targetNullValue = targetNullValue;
123+
return this;
124+
}
125+
126+
public PropertySettersBindingBuilder<T> Convert<Q>(Func<Q, T> convert)
127+
{
128+
if (valueConverter == null)
129+
{
130+
valueConverter = new ValueConverter();
131+
}
132+
133+
valueConverter.ConvertFunction = (object e) => convert((Q)e);
134+
converter = valueConverter;
135+
return this;
136+
}
137+
138+
public PropertySettersBindingBuilder<T> ConvertBack<Q>(Func<T, Q> convert)
139+
{
140+
if (valueConverter == null)
141+
{
142+
valueConverter = new ValueConverter();
143+
}
144+
145+
valueConverter.ConvertBackFunction = (T e) => convert(e);
146+
converter = valueConverter;
147+
return this;
148+
}
149+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
namespace FmgLib.MauiMarkup;
2+
3+
public sealed class PropertySettersDynamicResourcesBuilder<T> : IPropertySettersBuilder<T>
4+
{
5+
public PropertySettersContext<T> Context { get; set; }
6+
7+
string key = null;
8+
9+
public PropertySettersDynamicResourcesBuilder(PropertySettersContext<T> context)
10+
{
11+
Context = context;
12+
}
13+
14+
public bool Build()
15+
{
16+
if (!string.IsNullOrEmpty(key))
17+
{
18+
Context.XamlSetters.Add(new Setter { Property = Context.Property, Value = new Microsoft.Maui.Controls.Internals.DynamicResource(key) });
19+
}
20+
21+
return false;
22+
}
23+
24+
public PropertySettersDynamicResourcesBuilder<T> DynamicResource(string key) { this.key = key; return this; }
25+
}

0 commit comments

Comments
 (0)