-
Notifications
You must be signed in to change notification settings - Fork 1.8k
/
Copy pathElementHandler.cs
134 lines (101 loc) · 3.56 KB
/
ElementHandler.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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
using System;
namespace Microsoft.Maui.Handlers
{
public abstract partial class ElementHandler : IElementHandler
{
public static IPropertyMapper<IElement, IElementHandler> ElementMapper = new PropertyMapper<IElement, IElementHandler>()
{
};
public static CommandMapper<IElement, IElementHandler> ElementCommandMapper = new CommandMapper<IElement, IElementHandler>()
{
};
internal readonly IPropertyMapper _defaultMapper;
internal readonly CommandMapper? _commandMapper;
internal IPropertyMapper _mapper;
protected ElementHandler(IPropertyMapper mapper, CommandMapper? commandMapper = null)
{
_ = mapper ?? throw new ArgumentNullException(nameof(mapper));
_defaultMapper = mapper;
_mapper = _defaultMapper;
_commandMapper = commandMapper;
}
public IMauiContext? MauiContext { get; private set; }
public IServiceProvider? Services => MauiContext?.Services;
public object? PlatformView { get; private protected set; }
public IElement? VirtualView { get; private protected set; }
public virtual void SetMauiContext(IMauiContext mauiContext) =>
MauiContext = mauiContext;
public virtual void SetVirtualView(IElement view)
{
_ = view ?? throw new ArgumentNullException(nameof(view));
if (VirtualView == view)
return;
var oldVirtualView = VirtualView;
bool setupPlatformView = oldVirtualView == null;
VirtualView = view;
PlatformView ??= CreatePlatformElement();
if (VirtualView.Handler != this)
VirtualView.Handler = this;
// We set the previous virtual view to null after setting it on the incoming virtual view.
// This makes it easier for the incoming virtual view to have influence
// on how the exchange of handlers happens.
// We will just set the handler to null ourselves as a last resort cleanup
if (oldVirtualView?.Handler != null)
oldVirtualView.Handler = null;
if (setupPlatformView)
{
ConnectHandler(PlatformView);
}
_mapper = _defaultMapper;
if (VirtualView is IPropertyMapperView imv)
{
var map = imv.GetPropertyMapperOverrides();
if (map is not null)
{
map.Chained = new[] { _defaultMapper };
_mapper = map;
}
}
_mapper.UpdateProperties(this, VirtualView);
}
public virtual void UpdateValue(string property)
{
if (VirtualView == null)
return;
_mapper?.UpdateProperty(this, VirtualView, property);
}
public virtual void Invoke(string command, object? args)
{
if (VirtualView == null)
return;
_commandMapper?.Invoke(this, VirtualView, command, args);
}
private protected abstract object OnCreatePlatformElement();
object CreatePlatformElement() =>
OnCreatePlatformElement();
private protected abstract void OnConnectHandler(object platformView);
void ConnectHandler(object platformView) =>
OnConnectHandler(platformView);
private protected abstract void OnDisconnectHandler(object platformView);
void DisconnectHandler(object platformView)
{
OnDisconnectHandler(platformView);
// VirtualView has already been changed over to a new handler
if (VirtualView != null && VirtualView.Handler == this)
VirtualView.Handler = null;
VirtualView = null;
}
void IElementHandler.DisconnectHandler()
{
if (PlatformView != null && VirtualView != null)
{
// We set the PlatformView to null so no one outside of this handler tries to access
// PlatformView. PlatformView access should be isolated to the instance passed into
// DisconnectHandler
var oldPlatformView = PlatformView;
PlatformView = null;
DisconnectHandler(oldPlatformView);
}
}
}
}