Skip to content

Commit 368000a

Browse files
[net10.0] Trimmable view handlers (#28357)
* Add ElementHandlerAttribute * Add the attribute to Label and CheckBox * Use the attribute in MauiHandlersFactory * Add IRemappable and RemappingHelper * Add implementation of IRemappable to Label and CheckBox * Update app host builder * Fix MAUI handlers factory * Change TrySetValue from extension method to Element virtual method * Move big switch from GesturePlatformManager to VisualHandler and subclasses * Fix dereference of a possibly null reference * Fix remapping * Remove unnecessary changes * Fix attribute inheritance * Drop custom inheritance logic
1 parent e2c79eb commit 368000a

File tree

17 files changed

+195
-87
lines changed

17 files changed

+195
-87
lines changed

src/Controls/src/Core/CheckBox/CheckBox.Mapper.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,12 @@ namespace Microsoft.Maui.Controls
99
{
1010
public partial class CheckBox
1111
{
12-
internal new static void RemapForControls()
12+
static CheckBox() => RemapForControls();
13+
14+
private new static void RemapForControls()
1315
{
16+
VisualElement.RemapForControls();
17+
1418
CheckBoxHandler.Mapper.ReplaceMapping<ICheckBox, ICheckBoxHandler>(nameof(Color), MapColor);
1519
}
1620

src/Controls/src/Core/CheckBox/CheckBox.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ namespace Microsoft.Maui.Controls
77
{
88
/// <include file="../../docs/Microsoft.Maui.Controls/CheckBox.xml" path="Type[@FullName='Microsoft.Maui.Controls.CheckBox']/Docs/*" />
99
[DebuggerDisplay("{GetDebuggerDisplay(), nq}")]
10+
[ElementHandler<CheckBoxHandler>]
1011
public partial class CheckBox : View, IElementConfiguration<CheckBox>, IBorderElement, IColorElement, ICheckBox
1112
{
1213
readonly Lazy<PlatformConfigurationRegistry<CheckBox>> _platformConfigurationRegistry;
@@ -116,5 +117,16 @@ private protected override string GetDebuggerDisplay()
116117
{
117118
return $"{base.GetDebuggerDisplay()}, IsChecked = {IsChecked}";
118119
}
120+
121+
internal override bool TrySetValue(string text)
122+
{
123+
if (bool.TryParse(text, out bool result))
124+
{
125+
IsChecked = result;
126+
return true;
127+
}
128+
129+
return false;
130+
}
119131
}
120132
}

src/Controls/src/Core/Element/Element.Mapper.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@ namespace Microsoft.Maui.Controls
88
{
99
public partial class Element
1010
{
11+
static Element() => RemapIfNeeded();
12+
13+
internal static void RemapIfNeeded()
14+
{
15+
RemappingHelper.RemapIfNeeded(typeof(Element), RemapForControls);
16+
}
17+
1118
internal static void RemapForControls()
1219
{
1320
ViewHandler.ViewMapper.ReplaceMapping<Maui.IElement, IElementHandler>(AutomationProperties.IsInAccessibleTreeProperty.PropertyName, MapAutomationPropertiesIsInAccessibleTree);

src/Controls/src/Core/Element/Element.cs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1072,6 +1072,47 @@ HandlerDisconnectPolicy IHandlerDisconnectPolicies.DisconnectPolicy
10721072
set => HandlerProperties.SetDisconnectPolicy(this, value);
10731073
}
10741074

1075+
internal virtual bool TrySetValue(string text)
1076+
{
1077+
if (this is Label label)
1078+
{
1079+
label.Text = text;
1080+
return true;
1081+
}
1082+
else if (this is Entry entry)
1083+
{
1084+
entry.Text = text;
1085+
return true;
1086+
}
1087+
else if (this is Editor editor)
1088+
{
1089+
editor.Text = text;
1090+
return true;
1091+
}
1092+
else if (this is Switch sw && bool.TryParse(text, out bool swResult))
1093+
{
1094+
sw.IsToggled = swResult;
1095+
return true;
1096+
}
1097+
else if (this is RadioButton rb && bool.TryParse(text, out bool rbResult))
1098+
{
1099+
rb.IsChecked = rbResult;
1100+
return true;
1101+
}
1102+
else if (this is TimePicker tp && TimeSpan.TryParse(text, out TimeSpan tpResult))
1103+
{
1104+
tp.Time = tpResult;
1105+
return true;
1106+
}
1107+
else if (this is DatePicker dp && DateTime.TryParse(text, out DateTime dpResult))
1108+
{
1109+
dp.Date = dpResult;
1110+
return true;
1111+
}
1112+
1113+
return false;
1114+
}
1115+
10751116
class TemporaryWrapper : IList<Element>
10761117
{
10771118
IReadOnlyList<Element> _inner;

src/Controls/src/Core/Hosting/AppHostBuilderExtensions.cs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,13 +73,11 @@ internal static IMauiHandlersCollection AddControlsHandlers(this IMauiHandlersCo
7373
handlersCollection.AddHandler<ActivityIndicator, ActivityIndicatorHandler>();
7474
handlersCollection.AddHandler<BoxView, BoxViewHandler>();
7575
handlersCollection.AddHandler<Button, ButtonHandler>();
76-
handlersCollection.AddHandler<CheckBox, CheckBoxHandler>();
7776
handlersCollection.AddHandler<DatePicker, DatePickerHandler>();
7877
handlersCollection.AddHandler<Editor, EditorHandler>();
7978
handlersCollection.AddHandler<Entry, EntryHandler>();
8079
handlersCollection.AddHandler<GraphicsView, GraphicsViewHandler>();
8180
handlersCollection.AddHandler<Image, ImageHandler>();
82-
handlersCollection.AddHandler<Label, LabelHandler>();
8381
handlersCollection.AddHandler<Layout, LayoutHandler>();
8482
handlersCollection.AddHandler<Picker, PickerHandler>();
8583
handlersCollection.AddHandler<ProgressBar, ProgressBarHandler>();
@@ -263,12 +261,10 @@ static MauiAppBuilder ConfigureImageSourceHandlers(this MauiAppBuilder builder)
263261
internal static MauiAppBuilder RemapForControls(this MauiAppBuilder builder)
264262
{
265263
// Update the mappings for IView/View to work specifically for Controls
266-
Element.RemapForControls();
264+
Element.RemapIfNeeded();
267265
Application.RemapForControls();
268-
VisualElement.RemapForControls();
269-
Label.RemapForControls();
266+
VisualElement.RemapIfNeeded();
270267
Button.RemapForControls();
271-
CheckBox.RemapForControls();
272268
DatePicker.RemapForControls();
273269
RadioButton.RemapForControls();
274270
FlyoutPage.RemapForControls();

src/Controls/src/Core/Label/Label.Mapper.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,12 @@ namespace Microsoft.Maui.Controls
99
/// <include file="../../../docs/Microsoft.Maui.Controls/Label.xml" path="Type[@FullName='Microsoft.Maui.Controls.Label']/Docs/*" />
1010
public partial class Label
1111
{
12-
internal static new void RemapForControls()
12+
static Label() => RemapForControls();
13+
14+
private new static void RemapForControls()
1315
{
16+
VisualElement.RemapIfNeeded();
17+
1418
// Adjust the mappings to preserve Controls.Label legacy behaviors
1519
// ILabel does not include the TextType property, so we map it here to handle HTML text
1620
// And we map some of the other property handlers to Controls-specific versions that avoid stepping on HTML text settings

src/Controls/src/Core/Label/Label.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ namespace Microsoft.Maui.Controls
1515
/// <include file="../../docs/Microsoft.Maui.Controls/Label.xml" path="Type[@FullName='Microsoft.Maui.Controls.Label']/Docs/*" />
1616
[ContentProperty(nameof(Text))]
1717
[DebuggerDisplay("{GetDebuggerDisplay(), nq}")]
18+
[ElementHandler<LabelHandler>]
1819
public partial class Label : View, IFontElement, ITextElement, ITextAlignmentElement, ILineHeightElement, IElementConfiguration<Label>, IDecorableTextElement, IPaddingElement, ILabel
1920
{
2021
/// <summary>Bindable property for <see cref="HorizontalTextAlignment"/>.</summary>

src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.Windows.cs

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -88,25 +88,8 @@ public FrameworkElement? Container
8888
// Do we need to provide a hook for this in the handlers?
8989
// For now I just built this ugly matching statement
9090
// to replicate our handlers where we are setting this to true
91-
public bool PreventGestureBubbling
92-
{
93-
get
94-
{
95-
return Element switch
96-
{
97-
Button => true,
98-
CheckBox => true,
99-
DatePicker => true,
100-
Stepper => true,
101-
Slider => true,
102-
Switch => true,
103-
TimePicker => true,
104-
ImageButton => true,
105-
RadioButton => true,
106-
_ => false,
107-
};
108-
}
109-
}
91+
public bool PreventGestureBubbling =>
92+
(Element?.Handler as ViewHandler)?.PreventGestureBubbling ?? false;
11093

11194
public FrameworkElement? Control
11295
{

src/Controls/src/Core/ViewExtensions.cs

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -509,52 +509,6 @@ internal static List<Page> GetParentPages(this Page target)
509509
return text;
510510
}
511511

512-
internal static bool TrySetValue(this Element element, string text)
513-
{
514-
if (element is Label label)
515-
{
516-
label.Text = text;
517-
return true;
518-
}
519-
else if (element is Entry entry)
520-
{
521-
entry.Text = text;
522-
return true;
523-
}
524-
else if (element is Editor editor)
525-
{
526-
editor.Text = text;
527-
return true;
528-
}
529-
else if (element is CheckBox cb && bool.TryParse(text, out bool result))
530-
{
531-
cb.IsChecked = result;
532-
return true;
533-
}
534-
else if (element is Switch sw && bool.TryParse(text, out bool swResult))
535-
{
536-
sw.IsToggled = swResult;
537-
return true;
538-
}
539-
else if (element is RadioButton rb && bool.TryParse(text, out bool rbResult))
540-
{
541-
rb.IsChecked = rbResult;
542-
return true;
543-
}
544-
else if (element is TimePicker tp && TimeSpan.TryParse(text, out TimeSpan tpResult))
545-
{
546-
tp.Time = tpResult;
547-
return true;
548-
}
549-
else if (element is DatePicker dp && DateTime.TryParse(text, out DateTime dpResult))
550-
{
551-
dp.Date = dpResult;
552-
return true;
553-
}
554-
555-
return false;
556-
}
557-
558512
static internal bool RequestFocus(this VisualElement view)
559513
{
560514
// if there is an attached handler, we use that and we will end up in the MapFocus method below

src/Controls/src/Core/VisualElement/VisualElement.Mapper.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@ namespace Microsoft.Maui.Controls
88
/// <include file="../../../docs/Microsoft.Maui.Controls/VisualElement.xml" path="Type[@FullName='Microsoft.Maui.Controls.VisualElement']/Docs/*" />
99
public partial class VisualElement
1010
{
11+
static VisualElement() => RemapIfNeeded();
12+
13+
internal static new void RemapIfNeeded()
14+
{
15+
RemappingHelper.RemapIfNeeded(typeof(VisualElement), RemapForControls);
16+
}
17+
1118
internal static new void RemapForControls()
1219
{
1320
RemapForControls(ViewHandler.ViewMapper, ViewHandler.ViewCommandMapper);
@@ -17,6 +24,8 @@ internal static void RemapForControls(
1724
IPropertyMapper<IView, IViewHandler> viewMapper,
1825
CommandMapper<IView, IViewHandler> commandMapper)
1926
{
27+
Element.RemapIfNeeded();
28+
2029
#if WINDOWS
2130
viewMapper.ReplaceMapping<IView, IViewHandler>(PlatformConfiguration.WindowsSpecific.VisualElement.AccessKeyHorizontalOffsetProperty.PropertyName, MapAccessKeyHorizontalOffset);
2231
viewMapper.ReplaceMapping<IView, IViewHandler>(PlatformConfiguration.WindowsSpecific.VisualElement.AccessKeyPlacementProperty.PropertyName, MapAccessKeyPlacement);

0 commit comments

Comments
 (0)