Skip to content

Commit 1c75ab6

Browse files
committed
Update
- Changed Visual Element to be CallbackEventHandlers where Appropriate. - Added State Subscriptions for Binding to Value Changed Callbacks with Example of Usage. - Updated with a Field Example in MainView
1 parent c06c3fe commit 1c75ab6

File tree

3 files changed

+76
-9
lines changed

3 files changed

+76
-9
lines changed

Runtime/Scripts/BindingExtensions.cs

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,35 +17,38 @@ public static IDisposable BindEnabled(this VisualElement element, IReadOnlyReact
1717
element.SetEnabled(__property);
1818
});
1919
}
20-
public static IDisposable BindClick(this VisualElement element, ReactiveCommand<ClickEvent> command)
20+
public static IDisposable BindClick(this VisualElement element, IReactiveCommand<ClickEvent> command)
2121
{
2222
var d1 = element.BindEnabled(command.CanExecute);
23-
var d2 = element.BindVisualElementCallback(command);
23+
var d2 = element.BindCallback(command);
2424
return StableCompositeDisposable.Create(d1, d2);
2525
}
26-
public static IDisposable BindClick<TArgs>(this VisualElement element, ReactiveCommand<(ClickEvent, TArgs)> command, TArgs dataForCallback)
26+
public static IDisposable BindClick<TArgs>(this VisualElement element, IReactiveCommand<(ClickEvent, TArgs)> command, TArgs dataForCallback)
2727
{
2828
var d1 = element.BindEnabled(command.CanExecute);
29-
var d2 = element.BindVisualElementCallback(command, dataForCallback);
29+
var d2 = element.BindCallback(command, dataForCallback);
3030
return StableCompositeDisposable.Create(d1, d2);
3131
}
32-
public static IDisposable BindVisualElementCallback<TEventType>(this VisualElement element, EventCallback<TEventType> callback, TrickleDown trickleDown = TrickleDown.NoTrickleDown) where TEventType : EventBase<TEventType>, new()
32+
#endregion
33+
34+
#region Callback Event Handler
35+
public static IDisposable BindCallback<TEventType>(this CallbackEventHandler element, EventCallback<TEventType> callback, TrickleDown trickleDown = TrickleDown.NoTrickleDown) where TEventType : EventBase<TEventType>, new()
3336
{
3437
element.RegisterCallback(callback, trickleDown);
3538
return Disposable.Create(() => { element.UnregisterCallback(callback, trickleDown); });
3639
}
37-
public static IDisposable BindVisualElementCallback<TEventType, TUserArgsType>(this VisualElement element, EventCallback<TEventType, TUserArgsType> callback, TUserArgsType dataForCallback, TrickleDown trickleDown = TrickleDown.NoTrickleDown) where TEventType : EventBase<TEventType>, new()
40+
public static IDisposable BindCallback<TEventType, TUserArgsType>(this CallbackEventHandler element, EventCallback<TEventType, TUserArgsType> callback, TUserArgsType dataForCallback, TrickleDown trickleDown = TrickleDown.NoTrickleDown) where TEventType : EventBase<TEventType>, new()
3841
{
3942
element.RegisterCallback(callback, dataForCallback, trickleDown);
4043
return Disposable.Create(() => { element.UnregisterCallback(callback, trickleDown); });
4144
}
42-
public static IDisposable BindVisualElementCallback<TEventType>(this VisualElement element, ReactiveCommand<TEventType> command, TrickleDown trickleDown = TrickleDown.NoTrickleDown) where TEventType : EventBase<TEventType>, new()
45+
public static IDisposable BindCallback<TEventType>(this CallbackEventHandler element, IReactiveCommand<TEventType> command, TrickleDown trickleDown = TrickleDown.NoTrickleDown) where TEventType : EventBase<TEventType>, new()
4346
{
4447
var callback = new EventCallback<TEventType>((ev) => command.Execute(ev));
4548
element.RegisterCallback(callback, trickleDown);
4649
return Disposable.Create(() => { element.UnregisterCallback(callback, trickleDown); });
4750
}
48-
public static IDisposable BindVisualElementCallback<TEventType, TUserArgsType>(this VisualElement element, ReactiveCommand<(TEventType, TUserArgsType)> command, TUserArgsType dataForCallback, TrickleDown trickleDown = TrickleDown.NoTrickleDown) where TEventType : EventBase<TEventType>, new()
51+
public static IDisposable BindCallback<TEventType, TUserArgsType>(this CallbackEventHandler element, IReactiveCommand<(TEventType, TUserArgsType)> command, TUserArgsType dataForCallback, TrickleDown trickleDown = TrickleDown.NoTrickleDown) where TEventType : EventBase<TEventType>, new()
4952
{
5053
var callback = new EventCallback<TEventType, TUserArgsType>((ev, args) => command.Execute((ev, args)));
5154
element.RegisterCallback(callback, dataForCallback, trickleDown);
@@ -54,19 +57,60 @@ public static IDisposable BindClick<TArgs>(this VisualElement element, ReactiveC
5457
#endregion
5558

5659
#region Notifications
60+
public static IDisposable BindValueChanged<T>(this INotifyValueChanged<T> element, IReactiveCommand<ChangeEvent<T>> command)
61+
{
62+
var callback = new EventCallback<ChangeEvent<T>>((ev) => command.Execute(ev));
63+
element.RegisterValueChangedCallback(callback);
64+
return Disposable.Create(() => { element.UnregisterValueChangedCallback(callback); });
65+
}
5766
public static IDisposable BindValueChanged<T>(this INotifyValueChanged<T> element, IReactiveProperty<T> property)
5867
{
5968
var callback = new EventCallback<ChangeEvent<T>>((ev) => property.Value = ev.newValue);
6069
element.RegisterValueChangedCallback(callback);
6170
return Disposable.Create(() => { element.UnregisterValueChangedCallback(callback); });
6271
}
72+
/// <summary>
73+
/// Binds Element changes to Update Property Values.
74+
/// Then Initializes Values.
75+
/// </summary>
76+
/// <typeparam name="T"></typeparam>
77+
/// <param name="element">Element with Value Changed Callbacks</param>
78+
/// <param name="property">Reactive Property that value should change on a Value Changed Callback</param>
79+
/// <param name="stateIsProperty">Whether Default Value should be Default Property Value</param>
80+
/// <returns></returns>
81+
public static IDisposable BindValueChangedWithState<T>(this INotifyValueChanged<T> element, IReactiveProperty<T> property, bool stateIsProperty = true)
82+
{
83+
var d1 = BindValueChanged(element, property);
84+
if (stateIsProperty)
85+
{
86+
element.value = property.Value;
87+
}
88+
else
89+
{
90+
property.Value = element.value;
91+
}
92+
return d1;
93+
}
6394
public static IDisposable BindToValueChanged<T>(this INotifyValueChanged<T> element, IReactiveProperty<T> property)
6495
{
6596
return property.SubscribeWithState(element, (__property, __element) =>
6697
{
6798
__element.SetValueWithoutNotify(__property);
6899
});
69100
}
101+
public static IDisposable BindToValueChangedWithState<T>(this INotifyValueChanged<T> element, IReactiveProperty<T> property, bool stateIsProperty = true)
102+
{
103+
var d1 = BindToValueChanged(element, property);
104+
if (stateIsProperty)
105+
{
106+
element.value = property.Value;
107+
}
108+
else
109+
{
110+
property.Value = element.value;
111+
}
112+
return d1;
113+
}
70114
public static IDisposable BindTwoWayValueChanged<T>(this INotifyValueChanged<T> element, IReactiveProperty<T> property)
71115
{
72116
var d1 = BindValueChanged(element, property);

Samples/SamplesBasicUI/Scripts/MainView.cs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,25 @@ public class MainView : View<MainViewModel>
1212
{
1313
public override void OnActivation(MainViewModel viewModel, CompositeDisposable disposable)
1414
{
15+
//Grab Button
1516
Button button = Root.Q<Button>("ReactiveButton");
1617
Label label = Root.Q<Label>("Output");
18+
TextField field = Root.Q<TextField>("ReactiveTextField");
19+
Label fieldLabel = field.labelElement;
1720

21+
//Bind such that whenever OnButtonClick can Execute, you can click button.
22+
//Bind such that whenever Button is clicked, it executes OnButtonClick.
1823
button.BindClick(viewModel.OnButtonClick).AddTo(disposable);
1924

20-
label.BindTwoWayValueChanged(viewModel.DebugText).AddTo(disposable);
25+
//Bind such that whenever DebugText changes, it updates label value.
26+
label.BindToValueChanged(viewModel.DebugText).AddTo(disposable);
27+
28+
//Bind such that whenever field value changes, it executes OnTextFieldChange
29+
//Bind such that whenever field value changes, it updates reactive text. Initializes to default field value.
30+
field.BindValueChanged(viewModel.OnTextFieldChange).AddTo(disposable);
31+
field.BindValueChangedWithState(viewModel.ReactiveText, false).AddTo(disposable);
32+
//Bind such that whenever ReactiveText changes, it updates fieldlabel value.
33+
fieldLabel.BindToValueChanged(viewModel.ReactiveText).AddTo(disposable);
2134
}
2235
}
2336
}

Samples/SamplesBasicUI/Scripts/MainViewModel.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,23 @@ namespace RedMoon.ReactiveKit.Samples
1111
public class MainViewModel : ViewModel<MainViewModel>
1212
{
1313
public ReactiveProperty<string> DebugText { get; protected set; } = new ReactiveProperty<string>("");
14+
public ReactiveProperty<string> ReactiveText { get; protected set; } = new ReactiveProperty<string>("");
1415

1516
public ReactiveCommand<ClickEvent> OnButtonClick;
17+
public ReactiveCommand<ChangeEvent<string>> OnTextFieldChange;
1618

1719
public override void OnInitialization()
1820
{
1921
OnButtonClick = new ReactiveCommand<ClickEvent>();
2022
OnButtonClick.Subscribe((c) => UpdateDebugText(c, "Button Clicked"));
23+
24+
OnTextFieldChange = new ReactiveCommand<ChangeEvent<string>>();
25+
OnTextFieldChange.Subscribe((c) => UpdateDebugText(c, "Field Changed:"));
26+
}
27+
28+
private void UpdateDebugText(ChangeEvent<string> obj, string Text)
29+
{
30+
DebugText.Value += $"{Text} {obj.previousValue} -> {obj.newValue}\n";
2131
}
2232

2333
private void UpdateDebugText(ClickEvent obj, string Text)

0 commit comments

Comments
 (0)