forked from dotnet/maui
/
ContentConverter.cs
118 lines (97 loc) · 2.93 KB
/
ContentConverter.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#nullable disable
using System;
using System.Globalization;
using Microsoft.Maui.Controls.Internals;
namespace Microsoft.Maui.Controls
{
internal class ContentConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var presenter = parameter as ContentPresenter;
if (value is View view)
{
return ConfigureView(view, presenter);
}
if (value is string textContent)
{
return ConvertToLabel(textContent, presenter);
}
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
static View ConfigureView(View view, ContentPresenter presenter)
{
if (view is ITextElement && HasTemplateAncestor(presenter, typeof(ITextElement)))
{
BindTextProperties(view);
}
if (view is IFontElement && HasTemplateAncestor(presenter, typeof(IFontElement)))
{
BindFontProperties(view);
}
return view;
}
static Label ConvertToLabel(string textContent, ContentPresenter presenter)
{
var label = new Label
{
Text = textContent
};
if (HasTemplateAncestor(presenter, typeof(ITextElement)))
{
BindTextProperties(label);
}
if (HasTemplateAncestor(presenter, typeof(IFontElement)))
{
BindFontProperties(label);
}
return label;
}
static void BindTextProperties(BindableObject content)
{
BindProperty(content, TextElement.TextColorProperty, static (ITextElement te) => te.TextColor);
BindProperty(content, TextElement.CharacterSpacingProperty, static (ITextElement te) => te.CharacterSpacing);
BindProperty(content, TextElement.TextTransformProperty, static (ITextElement te) => te.TextTransform);
}
static void BindFontProperties(BindableObject content)
{
BindProperty(content, FontElement.FontAttributesProperty, static (IFontElement fe) => fe.FontAttributes);
BindProperty(content, FontElement.FontSizeProperty, static (IFontElement fe) => fe.FontSize);
BindProperty(content, FontElement.FontFamilyProperty, static (IFontElement fe) => fe.FontFamily);
}
static void BindProperty<TSource, TProperty>(
BindableObject content,
BindableProperty property,
Func<TSource, TProperty> getter)
{
if (content.IsSet(property) || content.GetIsBound(property))
{
// Don't override the property if user has already set it
return;
}
content.SetBinding(property, TypedBinding.ForSingleNestingLevel(
property.PropertyName, getter, source: new RelativeBindingSource(RelativeBindingSourceMode.FindAncestor, typeof(TSource))));
}
static bool HasTemplateAncestor(ContentPresenter presenter, Type type)
{
var parent = presenter?.Parent;
while (parent != null)
{
if (type.IsAssignableFrom(parent.GetType()))
{
return true;
}
if (parent is ContentView)
{
break;
}
parent = parent.Parent;
}
return false;
}
}
}