diff --git a/src/Tizen.NUI.Components/Controls/RecyclerView/Item/RecyclerViewItem.Internal.cs b/src/Tizen.NUI.Components/Controls/RecyclerView/Item/RecyclerViewItem.Internal.cs
index 7808987ba31..54285980c8d 100755
--- a/src/Tizen.NUI.Components/Controls/RecyclerView/Item/RecyclerViewItem.Internal.cs
+++ b/src/Tizen.NUI.Components/Controls/RecyclerView/Item/RecyclerViewItem.Internal.cs
@@ -227,6 +227,7 @@ protected override void OnEnabled(bool enabled)
protected override void OnBindingContextChanged()
{
PropagateBindingContext(this);
+ base.OnBindingContextChanged();
}
private void PropagateBindingContext(View parent)
diff --git a/src/Tizen.NUI/src/devel/Binding/BindingExtensions.cs b/src/Tizen.NUI/src/devel/Binding/BindingExtensions.cs
new file mode 100644
index 00000000000..8764109b279
--- /dev/null
+++ b/src/Tizen.NUI/src/devel/Binding/BindingExtensions.cs
@@ -0,0 +1,207 @@
+using System;
+using System.ComponentModel;
+using System.Reflection;
+using Tizen.NUI.BaseComponents;
+
+namespace Tizen.NUI.Binding
+{
+ ///
+ /// Provides extension methods for binding properties of a view model to a view.
+ ///
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public static class BindingExtensions
+ {
+ ///
+ /// Sets the binding for the specified view model property.
+ ///
+ /// The type of the view model.
+ /// The type of the view.
+ /// The view to bind to.
+ /// The view model to bind from.
+ /// The action to set the view property.
+ /// The path of the view model property.
+ /// The view.
+ public static TView SetBinding(this TView view, BindingSession vm, Action set, string path) where TView : View
+ {
+ _ = view ?? throw new ArgumentNullException(nameof(view));
+
+ var setter = new Action(vm =>
+ {
+ set.Invoke(vm, view);
+ });
+ vm.AddBinding(setter, path);
+ return view;
+ }
+
+ ///
+ /// Sets the binding for the specified view model property.
+ ///
+ /// The type of the view model.
+ /// The view to bind to.
+ /// The view model to bind from.
+ /// The action to set the view property.
+ /// The path of the view model property.
+ /// The view.
+ public static View SetBinding(this View view, BindingSession vm, Action set, string path)
+ {
+ vm.AddBinding(set, path);
+ return view;
+ }
+
+ ///
+ /// Sets the binding for the specified view model property.
+ ///
+ /// The type of the view model.
+ /// The view to bind to.
+ /// The binding session.
+ /// The path of the view property.
+ /// The path of the view model property.
+ /// The view.
+ public static View SetBinding(this View view, BindingSession session, string targetPath, string srcPath)
+ {
+ var setter = new Action(model =>
+ {
+ if (view.Disposed)
+ {
+ return;
+ }
+ var prop = view.GetType().GetProperty(targetPath, BindingFlags.Public | BindingFlags.Instance);
+ prop.SetValue(view, session.GetValue(srcPath));
+ });
+ session.AddBinding(setter, srcPath);
+ return view;
+ }
+
+ ///
+ /// Sets the binding for the specified view model property.
+ ///
+ /// The type of the view.
+ /// The type of the view model.
+ /// The type of the view property.
+ /// The view to bind to.
+ /// The binding session.
+ /// The view property.
+ /// The path of the view model property.
+ /// The view.
+ public static TView SetBinding(this TView view, BindingSession session, BindingProperty property, string path) where TView : View
+ {
+ var setter = new Action(model =>
+ {
+ if (view.Disposed)
+ {
+ return;
+ }
+
+ var value = session.GetValue(path);
+ // need to apply convertor if type was not mached
+ if (value != null && !typeof(TProperty).IsAssignableFrom(value.GetType()))
+ {
+ // only string type convert with ToString()
+ if (typeof(TProperty) == typeof(string))
+ {
+ value = value.ToString();
+ }
+ else
+ {
+ throw new InvalidCastException($"Cannot cast {value.GetType()} to {typeof(TProperty)}");
+ }
+ }
+ property.Setter(view, (TProperty)value);
+ });
+ session.AddBinding(setter, path);
+ return view;
+ }
+
+ ///
+ /// Sets the two-way binding for the specified view model property.
+ ///
+ /// The type of the view model.
+ /// The type of the view property.
+ /// The view to bind to.
+ /// The binding session.
+ /// The view property.
+ /// The path of the view model property.
+ /// The view.
+ public static View SetTwoWayBinding(this View view, BindingSession session, TwoWayBindingProperty property, string path)
+ {
+ var regit = new Action(act =>
+ {
+ property.AddObserver(view, act);
+ });
+ var unregit = new Action(act =>
+ {
+ property.RemoveObserver(view, act);
+ });
+ var setter = new Action(model =>
+ {
+ if (view.Disposed)
+ {
+ return;
+ }
+ property.Setter(view, (TProperty)session.GetValue(path));
+ });
+ var getter = new Func(() => property.Getter(view));
+ session.AddTwoWayBinding(regit, unregit, setter, getter, path);
+ return view;
+ }
+
+ ///
+ /// Sets the two-way binding for the specified view model property.
+ ///
+ /// The type of the view.
+ /// The type of the view model.
+ /// The type of the view property.
+ /// The to.
+ /// The binding session.
+ /// The view property.
+ /// The path of the view model property.
+ /// The view.
+ public static TView SetTwoWayBinding(this TView view, BindingSession session, TwoWayBindingProperty property, string path) where TView : View
+ {
+ var regit = new Action(act =>
+ {
+ property.AddObserver(view, act);
+ });
+ var unregit = new Action(act =>
+ {
+ property.RemoveObserver(view, act);
+ });
+ var setter = new Action(model =>
+ {
+ if (view.Disposed)
+ {
+ return;
+ }
+ property.Setter(view, (TProperty)session.GetValue(path));
+ });
+ var getter = new Func(() => property.Getter(view));
+ session.AddTwoWayBinding(regit, unregit, setter, getter, path);
+ return view;
+ }
+
+ ///
+ /// Gets the binding session for the specified view.
+ ///
+ /// The type of the view model.
+ /// The view.
+ /// The binding session.
+ public static BindingSession BindingSession(this View view)
+ {
+ return view.GetAttached>();
+ }
+
+ ///
+ /// Sets the binding session for the specified view.
+ ///
+ /// The type of the view model.
+ /// The type of the view.
+ /// The view.
+ /// The binding session.
+ /// The view.
+ public static T BindingSession(this T view, BindingSession session) where T : View
+ {
+ view.SetAttached(session);
+ return view;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Tizen.NUI/src/devel/Binding/BindingProperty.cs b/src/Tizen.NUI/src/devel/Binding/BindingProperty.cs
new file mode 100644
index 00000000000..fba9b374f6e
--- /dev/null
+++ b/src/Tizen.NUI/src/devel/Binding/BindingProperty.cs
@@ -0,0 +1,19 @@
+using System;
+using System.ComponentModel;
+
+namespace Tizen.NUI.Binding
+{
+ ///
+ /// The BindingProperty class represents a binding property for a view.
+ ///
+ /// The type of the view.
+ /// The type of the value.
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public class BindingProperty
+ {
+ ///
+ /// Gets or sets the setter action for the binding property.
+ ///
+ public Action Setter { get; set; }
+ }
+}
diff --git a/src/Tizen.NUI/src/devel/Binding/BindingSession.cs b/src/Tizen.NUI/src/devel/Binding/BindingSession.cs
new file mode 100644
index 00000000000..4c4c4cf78c1
--- /dev/null
+++ b/src/Tizen.NUI/src/devel/Binding/BindingSession.cs
@@ -0,0 +1,193 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Reflection;
+using Tizen.NUI.BaseComponents;
+
+namespace Tizen.NUI.Binding
+{
+ ///
+ /// BindingSession class provides a mechanism for binding properties of a view model to a view.
+ ///
+ /// The type of the view model.
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public class BindingSession : INotifyPropertyChanged, IDisposable
+ {
+ private List _bindingActions = new List();
+ private List _changedAction = new List();
+ private Dictionary> _observers = new Dictionary>();
+ private TViewModel _viewmodel;
+ private bool _disposed;
+
+ ///
+ /// Represents an event that is raised when a property value changes.
+ ///
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ ///
+ /// Gets or sets the view model.
+ ///
+ public TViewModel ViewModel
+ {
+ get => _viewmodel;
+ set
+ {
+ if (_viewmodel != null && _viewmodel is INotifyPropertyChanged noti)
+ {
+ noti.PropertyChanged -= OnPropertyChanged;
+ }
+ _viewmodel = value;
+
+ if (_viewmodel != null && _viewmodel is INotifyPropertyChanged newobj)
+ {
+ newobj.PropertyChanged += OnPropertyChanged;
+ }
+
+ UpdateViewModel();
+ }
+ }
+
+ ///
+ /// Updates the view model.
+ ///
+ /// The view model to update.
+ public void UpdateViewModel(TViewModel vm)
+ {
+ ViewModel = vm;
+ }
+
+ ///
+ /// Updates the view model.
+ ///
+ public void UpdateViewModel()
+ {
+ foreach (var action in _bindingActions)
+ {
+ action.Invoke();
+ }
+ }
+
+ ///
+ /// Adds a binding between a property of the view model and a property of the view.
+ ///
+ /// The setter method of the view.
+ /// The path of the property to bind.
+ public void AddBinding(Action setter, string path)
+ {
+ var action = new Action(() =>
+ {
+ if (ViewModel != null)
+ setter(ViewModel);
+ });
+ _bindingActions.Add(action);
+ PropertyChangedEventHandler handler = (s, e) =>
+ {
+ if (path == "*" || e.PropertyName == path || e.PropertyName == "*")
+ {
+ action();
+ }
+ };
+ _changedAction.Add(handler);
+ PropertyChanged += handler;
+ action.Invoke();
+ }
+
+ ///
+ /// Adds a two-way binding between a property of the view model and a property of the view.
+ ///
+ /// The type of the property to bind.
+ /// The registration method of the observer.
+ /// The unregistration method of the observer.
+ /// The setter method of the view.
+ /// The getter method of the view.
+ /// The path of the property to bind.
+ public void AddTwoWayBinding(Action register, Action unregister, Action setter, Func getter, string path)
+ {
+ var action = new Action(() =>
+ {
+ if (ViewModel != null)
+ SetValue(getter(), path);
+ });
+ _observers[action] = unregister;
+ register(action);
+ AddBinding(setter, path);
+ }
+
+ ///
+ /// Clears all bindings.
+ ///
+ public void ClearBinding()
+ {
+ foreach (var evtHandler in _changedAction)
+ {
+ PropertyChanged -= evtHandler;
+ }
+ foreach (var observer in _observers)
+ {
+ observer.Value.Invoke(observer.Key);
+ }
+ _observers.Clear();
+ _changedAction.Clear();
+ _bindingActions.Clear();
+ }
+
+ ///
+ /// Gets the value of a property of the view model.
+ ///
+ /// The name of the property.
+ /// The value of the property.
+ public object GetValue(string name)
+ {
+ if (name == ".")
+ return ViewModel;
+
+ var prop = ViewModel.GetType().GetProperty(name, BindingFlags.Instance | BindingFlags.Public);
+ if (prop == null)
+ {
+ Log.Error("NUI", $"Binding : Property {name} not found");
+ }
+ return prop?.GetValue(ViewModel) ?? null;
+ }
+
+ ///
+ /// Sets the value of a property of the view model.
+ ///
+ /// The value to set.
+ /// The name of the property.
+ public void SetValue(object obj, string name)
+ {
+ var prop = ViewModel.GetType().GetProperty(name, BindingFlags.Instance | BindingFlags.Public);
+ prop?.SetValue(ViewModel, obj);
+ }
+
+ ///
+ /// Releases all resources used by the current instance of the BindingSession class.
+ ///
+ public void Dispose()
+ {
+ Dispose(disposing: true);
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Provides a mechanism for releasing unmanaged resources used by the BindingSession class.
+ ///
+ /// True if the method is called from Dispose, false if it is called from the finalizer.
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!_disposed)
+ {
+ if (disposing)
+ {
+ ClearBinding();
+ }
+ _disposed = true;
+ }
+ }
+
+ private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ PropertyChanged?.Invoke(this, e);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Tizen.NUI/src/devel/Binding/TwoWayBindingProperty.cs b/src/Tizen.NUI/src/devel/Binding/TwoWayBindingProperty.cs
new file mode 100644
index 00000000000..c1c3d3a9cc7
--- /dev/null
+++ b/src/Tizen.NUI/src/devel/Binding/TwoWayBindingProperty.cs
@@ -0,0 +1,29 @@
+using System;
+using System.ComponentModel;
+
+namespace Tizen.NUI.Binding
+{
+ ///
+ /// This class represents a two-way binding property between a view and its value.
+ ///
+ /// The type of the view.
+ /// The type of the value.
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public class TwoWayBindingProperty : BindingProperty
+ {
+ ///
+ /// Gets or sets the function that retrieves the value from the view.
+ ///
+ public Func Getter { get; set; }
+
+ ///
+ /// Gets or sets the action that adds an observer to the view.
+ ///
+ public Action AddObserver { get; set; }
+
+ ///
+ /// Gets or sets the action that removes an observer from the view.
+ ///
+ public Action RemoveObserver { get; set; }
+ }
+}
diff --git a/src/Tizen.NUI/src/devel/Binding/ViewBindings.cs b/src/Tizen.NUI/src/devel/Binding/ViewBindings.cs
new file mode 100644
index 00000000000..fa57b7c86e3
--- /dev/null
+++ b/src/Tizen.NUI/src/devel/Binding/ViewBindings.cs
@@ -0,0 +1,193 @@
+using System;
+using System.ComponentModel;
+using System.Collections.Generic;
+using Tizen.NUI.BaseComponents;
+
+namespace Tizen.NUI.Binding
+{
+ ///
+ /// Provides a set of static properties that represent the binding properties of the class.
+ ///
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public static class ViewBindings
+ {
+ ///
+ /// Gets the binding property for the width of a .
+ ///
+ public static BindingProperty WidthProperty { get; } = new BindingProperty
+ {
+ Setter = (v, value) => v.SizeWidth = value,
+ };
+
+ ///
+ /// Gets the binding property for the height of a .
+ ///
+ public static BindingProperty HeightProperty { get; } = new BindingProperty
+ {
+ Setter = (v, value) => v.SizeHeight = value,
+ };
+
+ ///
+ /// Gets the binding property for the background color of a .
+ ///
+ public static BindingProperty BackgroundColorProperty { get; } = new BindingProperty
+ {
+ Setter = (v, value) => v.SetBackgroundColor(value),
+ };
+ }
+
+ ///
+ /// Provides a set of static properties that represent the data-binding capabilities of the class.
+ ///
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public static class TextLabelBindings
+ {
+ ///
+ /// Gets the binding property for the property.
+ ///
+ public static BindingProperty TextProperty { get; } = new BindingProperty
+ {
+ Setter = (v, value) =>
+ {
+ v.Text = value;
+ }
+ };
+
+ ///
+ /// Gets the binding property for the property.
+ ///
+ public static BindingProperty TextColorProperty { get; } = new BindingProperty
+ {
+ Setter = (v, value) => v.TextColor = value.ToReferenceType(),
+ };
+
+ ///
+ /// Gets the binding property for the property.
+ ///
+ public static BindingProperty FontSizeProperty { get; } = new BindingProperty
+ {
+ Setter = (v, value) => v.PointSize = value,
+ };
+ }
+
+ ///
+ /// This class provides a set of static properties for binding with control.
+ ///
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public static class TextFieldBindings
+ {
+ ///
+ /// The TextColorProperty is a bindable property that indicates the color of the text in the control.
+ ///
+ public static BindingProperty TextColorProperty { get; } = new BindingProperty
+ {
+ Setter = (v, value) => v.TextColor = value.ToReferenceType(),
+ };
+
+ ///
+ /// The FontSizeProperty is a bindable property that indicates the size of the font used to display the text in the control.
+ ///
+ public static BindingProperty FontSizeProperty { get; } = new BindingProperty
+ {
+ Setter = (v, value) => v.PointSize = value,
+ };
+
+ ///
+ /// The TextProperty is a two-way bindable property that indicates the text displayed in the control.
+ ///
+ public static TwoWayBindingProperty TextProperty { get; } = new TwoWayBindingProperty
+ {
+ Setter = (v, value) => v.Text = value,
+ Getter = v => v.Text,
+ AddObserver = (v, action) => v.TextChanged += EventHandlerHelper.Set>((s, e) => { action.Invoke(); }, action),
+ RemoveObserver = (v, action) => v.TextChanged -= EventHandlerHelper.Get>(action),
+ };
+ }
+
+ ///
+ /// Provides a set of static properties for binding TextEditor controls.
+ ///
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public static class TextEditorBindings
+ {
+ ///
+ /// The TextColorProperty is a bindable property that indicates the color of the text in the TextEditor control.
+ ///
+ public static BindingProperty TextColorProperty { get; } = new BindingProperty
+ {
+ Setter = (v, value) => v.TextColor = value.ToReferenceType(),
+ };
+
+ ///
+ /// The FontSizeProperty is a bindable property that indicates the size of the font used to display the text in the TextEditor control.
+ ///
+ public static BindingProperty FontSizeProperty { get; } = new BindingProperty
+ {
+ Setter = (v, value) => v.PointSize = value,
+ };
+
+ ///
+ /// The TextProperty is a two-way bindable property that indicates the text displayed in the TextEditor control.
+ ///
+ public static TwoWayBindingProperty TextProperty { get; } = new TwoWayBindingProperty
+ {
+ Setter = (v, value) => v.Text = value,
+ Getter = v => v.Text,
+ AddObserver = (v, action) => v.TextChanged += EventHandlerHelper.Set>((s, e) => { action.Invoke(); }, action),
+ RemoveObserver = (v, action) => v.TextChanged -= EventHandlerHelper.Get>(action),
+ };
+ }
+
+ ///
+ /// Provides a set of static properties that represent the bindable properties of the class.
+ ///
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public static class ImageViewBindings
+ {
+ ///
+ /// Represents the bindable property for the property.
+ ///
+ public static BindingProperty ResourceUrlProperty { get; } = new BindingProperty
+ {
+ Setter = (v, value) => v.ResourceUrl = value,
+ };
+ }
+
+ ///
+ /// EventHandlerHelper class provides a helper method to set and get event handlers using actions.
+ ///
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public static class EventHandlerHelper
+ {
+ private static Dictionary s_actionHandlerMap = new Dictionary();
+
+ ///
+ /// Sets the event handler for the given action.
+ ///
+ /// The type of the event handler.
+ /// The event handler to set.
+ /// The action to associate with the event handler.
+ /// The event handler that was set.
+ public static TEventHandler Set(TEventHandler handler, Action action) where TEventHandler : Delegate
+ {
+ s_actionHandlerMap[action] = handler;
+ return handler;
+ }
+
+ ///
+ /// Gets the event handler associated with the given action and removes the association.
+ ///
+ /// The type of the event handler.
+ /// The action to get the event handler for.
+ /// The event handler associated with the given action, or null if no association exists.
+ public static TEventHandler Get(Action action) where TEventHandler : Delegate
+ {
+ if (!s_actionHandlerMap.ContainsKey(action))
+ return null;
+
+ var handler = (TEventHandler)s_actionHandlerMap[action];
+ s_actionHandlerMap.Remove(action);
+ return handler;
+ }
+ }
+}
diff --git a/test/Tizen.NUI.StyleGuide/Tizen.NUI.StyleGuide.cs b/test/Tizen.NUI.StyleGuide/Tizen.NUI.StyleGuide.cs
index da74df0e398..51e0615fe8e 100644
--- a/test/Tizen.NUI.StyleGuide/Tizen.NUI.StyleGuide.cs
+++ b/test/Tizen.NUI.StyleGuide/Tizen.NUI.StyleGuide.cs
@@ -22,6 +22,7 @@
using Tizen.NUI.Components;
using Tizen.NUI.BaseComponents;
using Tizen.NUI.Binding;
+//using Tizen.NUI.Bindings;
using System.Reflection;
namespace Tizen.NUI.StyleGuide
@@ -307,11 +308,16 @@ private void SetMainPage()
ItemsLayouter = new LinearLayouter(),
ItemTemplate = new DataTemplate(() =>
{
+ var session = new BindingSession();
DefaultLinearItem item = new DefaultLinearItem()
{
WidthSpecification = LayoutParamPolicies.MatchParent,
};
- item.Label.SetBinding(TextLabel.TextProperty, "ViewLabel");
+ item.BindingContextChanged += (sender, e) =>
+ {
+ session.ViewModel = (ControlMenu)item.BindingContext;
+ };
+ item.Label.SetBinding(session, TextLabelBindings.TextProperty, "ViewLabel");
item.Label.HorizontalAlignment = HorizontalAlignment.Begin;
item.Focusable = true; //BaseComponents' Focusable is false as a default value, true should be set to navigate key focus.
return item;