-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
/
InstancedBinding.cs
172 lines (153 loc) · 7.08 KB
/
InstancedBinding.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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
using System;
using System.ComponentModel;
using Avalonia.Data.Core;
using Avalonia.Reactive;
using ObservableEx = Avalonia.Reactive.Observable;
namespace Avalonia.Data
{
/// <summary>
/// Holds the result of calling <see cref="IBinding.Initiate"/>.
/// </summary>
/// <remarks>
/// Whereas an <see cref="IBinding"/> holds a description of a binding such as "Bind to the X
/// property on a control's DataContext"; this class represents a binding that has been
/// *instanced* by calling <see cref="IBinding.Initiate(AvaloniaObject, AvaloniaProperty, object, bool)"/>
/// on a target object.
/// </remarks>
public sealed class InstancedBinding
{
private readonly AvaloniaObject? _target;
private readonly UntypedBindingExpressionBase? _expression;
private IObservable<object?>? _observable;
/// <summary>
/// Initializes a new instance of the <see cref="InstancedBinding"/> class.
/// </summary>
/// <param name="source">The binding source.</param>
/// <param name="mode">The binding mode.</param>
/// <param name="priority">The priority of the binding.</param>
/// <remarks>
/// This constructor can be used to create any type of binding and as such requires an
/// <see cref="IObservable{Object}"/> as the binding source because this is the only binding
/// source which can be used for all binding modes. If you wish to create an instance with
/// something other than a subject, use one of the static creation methods on this class.
/// </remarks>
internal InstancedBinding(IObservable<object?> source, BindingMode mode, BindingPriority priority)
{
Mode = mode;
Priority = priority;
_observable = source ?? throw new ArgumentNullException(nameof(source));
}
internal InstancedBinding(
UntypedBindingExpressionBase source,
BindingMode mode,
BindingPriority priority)
{
Mode = mode;
Priority = priority;
_expression = source ?? throw new ArgumentNullException(nameof(source));
}
internal InstancedBinding(
AvaloniaObject? target,
UntypedBindingExpressionBase source,
BindingMode mode,
BindingPriority priority)
{
Mode = mode;
Priority = priority;
_expression = source ?? throw new ArgumentNullException(nameof(source));
_target = target;
}
/// <summary>
/// Gets the binding mode with which the binding was initiated.
/// </summary>
public BindingMode Mode { get; }
/// <summary>
/// Gets the binding priority.
/// </summary>
public BindingPriority Priority { get; }
/// <summary>
/// Gets the binding source observable.
/// </summary>
public IObservable<object?> Source => _observable ??= _expression!.ToObservable(_target);
[Obsolete("Use Source property"), EditorBrowsable(EditorBrowsableState.Never)]
public IObservable<object?> Observable => Source;
internal UntypedBindingExpressionBase? Expression => _expression;
/// <summary>
/// Creates a new one-time binding with a fixed value.
/// </summary>
/// <param name="value">The value.</param>
/// <param name="priority">The priority of the binding.</param>
/// <returns>An <see cref="InstancedBinding"/> instance.</returns>
public static InstancedBinding OneTime(
object value,
BindingPriority priority = BindingPriority.LocalValue)
{
return new InstancedBinding(ObservableEx.SingleValue(value), BindingMode.OneTime, priority);
}
/// <summary>
/// Creates a new one-time binding.
/// </summary>
/// <param name="observable">The source observable.</param>
/// <param name="priority">The priority of the binding.</param>
/// <returns>An <see cref="InstancedBinding"/> instance.</returns>
public static InstancedBinding OneTime(
IObservable<object?> observable,
BindingPriority priority = BindingPriority.LocalValue)
{
_ = observable ?? throw new ArgumentNullException(nameof(observable));
return new InstancedBinding(observable, BindingMode.OneTime, priority);
}
/// <summary>
/// Creates a new one-way binding.
/// </summary>
/// <param name="observable">The source observable.</param>
/// <param name="priority">The priority of the binding.</param>
/// <returns>An <see cref="InstancedBinding"/> instance.</returns>
public static InstancedBinding OneWay(
IObservable<object?> observable,
BindingPriority priority = BindingPriority.LocalValue)
{
_ = observable ?? throw new ArgumentNullException(nameof(observable));
return new InstancedBinding(observable, BindingMode.OneWay, priority);
}
/// <summary>
/// Creates a new one-way to source binding.
/// </summary>
/// <param name="observer">The binding source.</param>
/// <param name="priority">The priority of the binding.</param>
/// <returns>An <see cref="InstancedBinding"/> instance.</returns>
public static InstancedBinding OneWayToSource(
IObserver<object?> observer,
BindingPriority priority = BindingPriority.LocalValue)
{
_ = observer ?? throw new ArgumentNullException(nameof(observer));
return new InstancedBinding((IObservable<object?>)observer, BindingMode.OneWayToSource, priority);
}
/// <summary>
/// Creates a new two-way binding.
/// </summary>
/// <param name="observable">The binding source.</param>
/// <param name="observer">The binding source.</param>
/// <param name="priority">The priority of the binding.</param>
/// <returns>An <see cref="InstancedBinding"/> instance.</returns>
public static InstancedBinding TwoWay(
IObservable<object?> observable,
IObserver<object?> observer,
BindingPriority priority = BindingPriority.LocalValue)
{
_ = observable ?? throw new ArgumentNullException(nameof(observable));
_ = observer ?? throw new ArgumentNullException(nameof(observer));
var subject = observable == observer ? observable : new CombinedSubject<object?>(observer, observable);
return new InstancedBinding(subject, BindingMode.TwoWay, priority);
}
/// <summary>
/// Creates a copy of the <see cref="InstancedBinding"/> with a different priority.
/// </summary>
/// <param name="priority">The priority of the binding.</param>
/// <returns>An <see cref="InstancedBinding"/> instance.</returns>
public InstancedBinding WithPriority(BindingPriority priority)
{
return new InstancedBinding(Source, Mode, priority);
}
}
}