[NUI][NUI.Components] Fix SVACE issue in CollectionView.
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI.Components / Controls / RecyclerView / CollectionView.cs
index fc7e437..95c41dc 100755 (executable)
@@ -29,7 +29,7 @@ namespace Tizen.NUI.Components
     /// Selectable RecyclerView that presenting a collection of items with variable layouters.
     /// </summary>
     /// <since_tizen> 9 </since_tizen>
-    public class CollectionView : RecyclerView
+    public partial class CollectionView : RecyclerView
     {
         /// <summary>
         /// Binding Property of selected item in single selection.
@@ -39,23 +39,43 @@ namespace Tizen.NUI.Components
             BindableProperty.Create(nameof(SelectedItem), typeof(object), typeof(CollectionView), null,
                 propertyChanged: (bindable, oldValue, newValue) =>
                 {
-                    var colView = (CollectionView)bindable;
+                    var colView = bindable as CollectionView;
+                    if (colView == null)
+                    {
+                        throw new Exception("Bindable object is not CollectionView.");
+                    }
+
                     oldValue = colView.selectedItem;
                     colView.selectedItem = newValue;
                     var args = new SelectionChangedEventArgs(oldValue, newValue);
 
                     foreach (RecyclerViewItem item in colView.ContentContainer.Children.Where((item) => item is RecyclerViewItem))
                     {
-                        if (item.BindingContext == null) continue;
-                        if (item.BindingContext == oldValue) item.IsSelected = false;
-                        else if (item.BindingContext == newValue) item.IsSelected = true;
+                        if (item.BindingContext == null)
+                        {
+                            continue;
+                        }
+
+                        if (item.BindingContext == oldValue)
+                        {
+                            item.IsSelected = false;
+                        }
+                        else if (item.BindingContext == newValue)
+                        {
+                            item.IsSelected = true;
+                        }
                     }
 
                     SelectionPropertyChanged(colView, args);
                 },
                 defaultValueCreator: (bindable) =>
                 {
-                    var colView = (CollectionView)bindable;
+                    var colView = bindable as CollectionView;
+                    if (colView == null)
+                    {
+                        throw new Exception("Bindable object is not CollectionView.");
+                    }
+
                     return colView.selectedItem;
                 });
 
@@ -67,7 +87,12 @@ namespace Tizen.NUI.Components
             BindableProperty.Create(nameof(SelectedItems), typeof(IList<object>), typeof(CollectionView), null,
                 propertyChanged: (bindable, oldValue, newValue) =>
                 {
-                    var colView = (CollectionView)bindable;
+                    var colView = bindable as CollectionView;
+                    if (colView == null)
+                    {
+                        throw new Exception("Bindable object is not CollectionView.");
+                    }
+
                     var oldSelection = colView.selectedItems ?? selectEmpty;
                     //FIXME : CoerceSelectedItems calls only isCreatedByXaml
                     var newSelection = (SelectionList)CoerceSelectedItems(colView, newValue);
@@ -76,7 +101,12 @@ namespace Tizen.NUI.Components
                 },
                 defaultValueCreator: (bindable) =>
                 {
-                    var colView = (CollectionView)bindable;
+                    var colView = bindable as CollectionView;
+                    if (colView == null)
+                    {
+                        throw new Exception("Bindable object is not CollectionView.");
+                    }
+
                     colView.selectedItems = colView.selectedItems ?? new SelectionList(colView);
                     return colView.selectedItems;
                 });
@@ -89,66 +119,25 @@ namespace Tizen.NUI.Components
             BindableProperty.Create(nameof(SelectionMode), typeof(ItemSelectionMode), typeof(CollectionView), ItemSelectionMode.None,
                 propertyChanged: (bindable, oldValue, newValue) =>
                 {
-                    var colView = (CollectionView)bindable;
+                    var colView = bindable as CollectionView;
+                    if (colView == null)
+                    {
+                        throw new Exception("Bindable object is not CollectionView.");
+                    }
+
                     oldValue = colView.selectionMode;
                     colView.selectionMode = (ItemSelectionMode)newValue;
                     SelectionModePropertyChanged(colView, oldValue, newValue);
                 },
                 defaultValueCreator: (bindable) =>
                 {
-                    var colView = (CollectionView)bindable;
-                    return colView.selectionMode;
-                });
-
-        /// <summary>
-        /// Binding Property of items data source.
-        /// </summary>
-        [EditorBrowsable(EditorBrowsableState.Never)]
-        public static readonly BindableProperty ItemsSourceProperty =
-            BindableProperty.Create(nameof(ItemsSource), typeof(IEnumerable), typeof(CollectionView), null,
-                propertyChanged: (bindable, oldValue, newValue) =>
-                {
-                    var colView = (CollectionView)bindable;
-                    oldValue = colView.itemsSource;
-
-                    if (oldValue != null)
+                    var colView = bindable as CollectionView;
+                    if (colView == null)
                     {
-                        // Clearing old data!
-                        if (oldValue is INotifyCollectionChanged prevNotifyCollectionChanged)
-                        {
-                            prevNotifyCollectionChanged.CollectionChanged -= colView.CollectionChanged;
-                        }
-                        if (colView.selectedItem != null) colView.selectedItem = null;
-                        colView.selectedItems?.Clear();
+                        throw new Exception("Bindable object is not CollectionView.");
                     }
 
-                    colView.itemsSource = (IEnumerable)newValue;
-
-                    if (newValue == null)
-                    {
-                        colView.InternalItemSource?.Dispose();
-                        colView.InternalItemSource = null;
-                        colView.itemsLayouter?.Clear();
-                        colView.ClearCache();
-                        return;
-                    }
-                    if (newValue is INotifyCollectionChanged newNotifyCollectionChanged)
-                    {
-                        newNotifyCollectionChanged.CollectionChanged += colView.CollectionChanged;
-                    }
-
-                    colView.InternalItemSource?.Dispose();
-                    colView.InternalItemSource = ItemsSourceFactory.Create(colView);
-
-                    if (colView.itemsLayouter == null) return;
-
-                    colView.needInitalizeLayouter = true;
-                    colView.Init();
-                },
-                defaultValueCreator: (bindable) =>
-                {
-                    var colView = (CollectionView)bindable;
-                    return colView.itemsSource;
+                    return colView.selectionMode;
                 });
 
 
@@ -167,8 +156,6 @@ namespace Tizen.NUI.Components
         private ItemSelectionMode selectionMode = ItemSelectionMode.None;
         private RecyclerViewItem header;
         private RecyclerViewItem footer;
-        private View focusedView;
-        private int prevFocusedDataIndex = 0;
         private List<RecyclerViewItem> recycleGroupHeaderCache { get; } = new List<RecyclerViewItem>();
         private List<RecyclerViewItem> recycleGroupFooterCache { get; } = new List<RecyclerViewItem>();
         private bool delayedScrollTo;
@@ -177,14 +164,19 @@ namespace Tizen.NUI.Components
         private bool delayedIndexScrollTo;
         private (int index, bool anim, ItemScrollTo scrollTo) delayedIndexScrollToParam;
 
+        private void Initialize()
+        {
+            FocusGroup = true;
+            SetKeyboardNavigationSupport(true);
+        }
+
         /// <summary>
         /// Base constructor.
         /// </summary>
         /// <since_tizen> 9 </since_tizen>
         public CollectionView() : base()
         {
-            FocusGroup = true;
-            SetKeyboardNavigationSupport(true);
+            Initialize();
         }
 
         /// <summary>
@@ -212,6 +204,16 @@ namespace Tizen.NUI.Components
         }
 
         /// <summary>
+        /// Creates a new instance of a CollectionView with style.
+        /// </summary>
+        /// <param name="style">A style applied to the newly created CollectionView.</param>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public CollectionView(ControlStyle style) : base(style)
+        {
+            Initialize();
+        }
+
+        /// <summary>
         /// Event of Selection changed.
         /// previous selection list and current selection will be provided.
         /// </summary>
@@ -255,8 +257,56 @@ namespace Tizen.NUI.Components
         /// <since_tizen> 9 </since_tizen>
         public override IEnumerable ItemsSource
         {
-            get => (IEnumerable)GetValue(ItemsSourceProperty);
-            set => SetValue(ItemsSourceProperty, value);
+            get => GetValue(RecyclerView.ItemsSourceProperty) as IEnumerable;
+            set => SetValue(RecyclerView.ItemsSourceProperty, value);
+        }
+
+        internal override IEnumerable InternalItemsSource
+        {
+            get
+            {
+                return itemsSource;
+            }
+            set
+            {
+                if (itemsSource != null)
+                {
+                    // Clearing old data!
+                    if (itemsSource is INotifyCollectionChanged prevNotifyCollectionChanged)
+                    {
+                        prevNotifyCollectionChanged.CollectionChanged -= CollectionChanged;
+                    }
+                    if (selectedItem != null)
+                    {
+                        selectedItem = null;
+                    }
+                    selectedItems?.Clear();
+                }
+
+                itemsSource = value as IEnumerable;
+
+                if (itemsSource == null)
+                {
+                    InternalItemSource?.Dispose();
+                    InternalItemSource = null;
+                    itemsLayouter?.Clear();
+                    ClearCache();
+                    return;
+                }
+                if (itemsSource is INotifyCollectionChanged newNotifyCollectionChanged)
+                {
+                    newNotifyCollectionChanged.CollectionChanged += CollectionChanged;
+                }
+
+                InternalItemSource?.Dispose();
+                InternalItemSource = ItemsSourceFactory.Create(this);
+
+                if (itemsLayouter == null) return;
+
+                needInitalizeLayouter = true;
+                ReinitializeLayout();
+
+            }
         }
 
         /// <summary>
@@ -270,6 +320,18 @@ namespace Tizen.NUI.Components
         {
             get
             {
+                return GetValue(ItemTemplateProperty) as DataTemplate;
+            }
+            set
+            {
+                SetValue(ItemTemplateProperty, value);
+                NotifyPropertyChanged();
+            }
+        }
+        internal override DataTemplate InternalItemTemplate
+        {
+            get
+            {
                 return itemTemplate;
             }
             set
@@ -281,7 +343,7 @@ namespace Tizen.NUI.Components
                 }
 
                 needInitalizeLayouter = true;
-                Init();
+                ReinitializeLayout();
             }
         }
 
@@ -297,6 +359,22 @@ namespace Tizen.NUI.Components
         {
             get
             {
+                return GetValue(ItemsLayouterProperty) as ItemsLayouter;
+            }
+            set
+            {
+                SetValue(ItemsLayouterProperty, value);
+                NotifyPropertyChanged();
+            }
+        }
+
+
+        /// <inheritdoc/>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        protected override ItemsLayouter InternalItemsLayouter
+        {
+            get
+            {
                 return itemsLayouter;
             }
             set
@@ -320,7 +398,7 @@ namespace Tizen.NUI.Components
                 {
                     itemsLayouter.Padding = new Extents(layouterStyle.Padding);
                 }
-                Init();
+                ReinitializeLayout();
             }
         }
 
@@ -332,6 +410,18 @@ namespace Tizen.NUI.Components
         {
             get
             {
+                return (Direction)GetValue(ScrollingDirectionProperty);
+            }
+            set
+            {
+                SetValue(ScrollingDirectionProperty, value);
+                NotifyPropertyChanged();
+            }
+        }
+        private Direction InternalScrollingDirection
+        {
+            get
+            {
                 return base.ScrollingDirection;
             }
             set
@@ -340,7 +430,7 @@ namespace Tizen.NUI.Components
                 {
                     base.ScrollingDirection = value;
                     needInitalizeLayouter = true;
-                    Init();
+                    ReinitializeLayout();
                 }
             }
         }
@@ -361,7 +451,7 @@ namespace Tizen.NUI.Components
         /// <since_tizen> 9 </since_tizen>
         public IList<object> SelectedItems
         {
-            get => (IList<object>)GetValue(SelectedItemsProperty);
+            get => GetValue(SelectedItemsProperty) as IList<object>;
             // set => SetValue(SelectedItemsProperty, new SelectionList(this, value));
         }
 
@@ -379,13 +469,37 @@ namespace Tizen.NUI.Components
         /// Command of selection changed.
         /// </summary>
         [EditorBrowsable(EditorBrowsableState.Never)]
-        public ICommand SelectionChangedCommand { set; get; }
+        public ICommand SelectionChangedCommand
+        {
+            get
+            {
+                return GetValue(SelectionChangedCommandProperty) as ICommand;
+            }
+            set
+            {
+                SetValue(SelectionChangedCommandProperty, value);
+                NotifyPropertyChanged();
+            }
+        }
+        private ICommand InternalSelectionChangedCommand { set; get; }
 
         /// <summary>
         /// Command parameter of selection changed.
         /// </summary>
         [EditorBrowsable(EditorBrowsableState.Never)]
-        public object SelectionChangedCommandParameter { set; get; }
+        public object SelectionChangedCommandParameter
+        {
+            get
+            {
+                return GetValue(SelectionChangedCommandParameterProperty);
+            }
+            set
+            {
+                SetValue(SelectionChangedCommandParameterProperty, value);
+                NotifyPropertyChanged();
+            }
+        }
+        private object InternalSelectionChangedCommandParameter { set; get; }
 
         /// <summary>
         /// Header item placed in top-most position.
@@ -394,6 +508,18 @@ namespace Tizen.NUI.Components
         /// <since_tizen> 9 </since_tizen>
         public RecyclerViewItem Header
         {
+            get
+            {
+                return GetValue(HeaderProperty) as RecyclerViewItem;
+            }
+            set
+            {
+                SetValue(HeaderProperty, value);
+                NotifyPropertyChanged();
+            }
+        }
+        private RecyclerViewItem InternalHeader
+        {
             get => header;
             set
             {
@@ -415,7 +541,7 @@ namespace Tizen.NUI.Components
                     InternalItemSource.HasHeader = (value != null);
                 }
                 needInitalizeLayouter = true;
-                Init();
+                ReinitializeLayout();
             }
         }
 
@@ -426,6 +552,18 @@ namespace Tizen.NUI.Components
         /// <since_tizen> 9 </since_tizen>
         public RecyclerViewItem Footer
         {
+            get
+            {
+                return GetValue(FooterProperty) as RecyclerViewItem;
+            }
+            set
+            {
+                SetValue(FooterProperty, value);
+                NotifyPropertyChanged();
+            }
+        }
+        private RecyclerViewItem InternalFooter
+        {
             get => footer;
             set
             {
@@ -447,7 +585,7 @@ namespace Tizen.NUI.Components
                     InternalItemSource.HasFooter = (value != null);
                 }
                 needInitalizeLayouter = true;
-                Init();
+                ReinitializeLayout();
             }
         }
 
@@ -457,6 +595,18 @@ namespace Tizen.NUI.Components
         [EditorBrowsable(EditorBrowsableState.Never)]
         public bool IsGrouped
         {
+            get
+            {
+                return (bool)GetValue(IsGroupedProperty);
+            }
+            set
+            {
+                SetValue(IsGroupedProperty, value);
+                NotifyPropertyChanged();
+            }
+        }
+        private bool InternalIsGrouped
+        {
             get => isGrouped;
             set
             {
@@ -469,8 +619,11 @@ namespace Tizen.NUI.Components
                     InternalItemSource = null;
                 }
                 if (ItemsSource != null)
+                {
                     InternalItemSource = ItemsSourceFactory.Create(this);
-                Init();
+                }
+
+                ReinitializeLayout();
             }
         }
 
@@ -478,27 +631,44 @@ namespace Tizen.NUI.Components
         ///  DataTemplate of group header.
         /// </summary>
         /// <remarks>Please note that, internal index will be increased by group header.
-        /// GroupHeaderTemplate is essential for groupable view.</remarks>        
+        /// GroupHeaderTemplate is essential for groupable view.</remarks>
         [EditorBrowsable(EditorBrowsableState.Never)]
         public DataTemplate GroupHeaderTemplate
         {
             get
             {
+                return GetValue(GroupHeaderTemplateProperty) as DataTemplate;
+            }
+            set
+            {
+                SetValue(GroupHeaderTemplateProperty, value);
+                NotifyPropertyChanged();
+            }
+        }
+        private DataTemplate InternalGroupHeaderTemplate
+        {
+            get
+            {
                 return groupHeaderTemplate;
             }
             set
             {
                 groupHeaderTemplate = value;
                 needInitalizeLayouter = true;
+
                 //Need to re-intialize Internal Item Source.
                 if (InternalItemSource != null)
                 {
                     InternalItemSource.Dispose();
                     InternalItemSource = null;
                 }
+
                 if (ItemsSource != null)
+                {
                     InternalItemSource = ItemsSourceFactory.Create(this);
-                Init();
+                }
+
+                ReinitializeLayout();
             }
         }
 
@@ -511,21 +681,38 @@ namespace Tizen.NUI.Components
         {
             get
             {
+                return GetValue(GroupFooterTemplateProperty) as DataTemplate;
+            }
+            set
+            {
+                SetValue(GroupFooterTemplateProperty, value);
+                NotifyPropertyChanged();
+            }
+        }
+        private DataTemplate InternalGroupFooterTemplate
+        {
+            get
+            {
                 return groupFooterTemplate;
             }
             set
             {
                 groupFooterTemplate = value;
                 needInitalizeLayouter = true;
+
                 //Need to re-intialize Internal Item Source.
                 if (InternalItemSource != null)
                 {
                     InternalItemSource.Dispose();
                     InternalItemSource = null;
                 }
+
                 if (ItemsSource != null)
+                {
                     InternalItemSource = ItemsSourceFactory.Create(this);
-                Init();
+                }
+
+                ReinitializeLayout();
             }
         }
 
@@ -557,7 +744,10 @@ namespace Tizen.NUI.Components
             base.OnRelayout(size, container);
 
             wasRelayouted = true;
-            if (needInitalizeLayouter) Init();
+            if (needInitalizeLayouter)
+            {
+                ReinitializeLayout();
+            }
         }
 
         /// <inheritdoc/>
@@ -576,121 +766,6 @@ namespace Tizen.NUI.Components
             base.NotifyDataSetChanged();
         }
 
-        /// <inheritdoc/>
-        [EditorBrowsable(EditorBrowsableState.Never)]
-        public override View GetNextFocusableView(View currentFocusedView, View.FocusDirection direction, bool loopEnabled)
-        {
-            View nextFocusedView = null;
-
-            if (focusedView == null)
-            {
-                // If focusedView is null, find child which has previous data index
-                if (ContentContainer.Children.Count > 0 && InternalItemSource.Count > 0)
-                {
-                    for (int i = 0; i < ContentContainer.Children.Count; i++)
-                    {
-                        RecyclerViewItem item = Children[i] as RecyclerViewItem;
-                        if (item?.Index == prevFocusedDataIndex)
-                        {
-                            nextFocusedView = item;
-                            break;
-                        }
-                    }
-                }
-            }
-            else
-            {
-                // If this is not first focus, request next focus to Layouter
-                nextFocusedView = ItemsLayouter?.RequestNextFocusableView(currentFocusedView, direction, loopEnabled);
-            }
-
-            if (nextFocusedView != null)
-            {
-                // Check next focused view is inside of visible area.
-                // If it is not, move scroll position to make it visible.
-                Position scrollPosition = ContentContainer.CurrentPosition;
-                float targetPosition = -(ScrollingDirection == Direction.Horizontal ? scrollPosition.X : scrollPosition.Y);
-
-                float left = nextFocusedView.Position.X;
-                float right = nextFocusedView.Position.X + nextFocusedView.Size.Width;
-                float top = nextFocusedView.Position.Y;
-                float bottom = nextFocusedView.Position.Y + nextFocusedView.Size.Height;
-
-                float visibleRectangleLeft = -scrollPosition.X;
-                float visibleRectangleRight = -scrollPosition.X + Size.Width;
-                float visibleRectangleTop = -scrollPosition.Y;
-                float visibleRectangleBottom = -scrollPosition.Y + Size.Height;
-
-                if (ScrollingDirection == Direction.Horizontal)
-                {
-                    if ((direction == View.FocusDirection.Left || direction == View.FocusDirection.Up) && left < visibleRectangleLeft)
-                    {
-                        targetPosition = left;
-                    }
-                    else if ((direction == View.FocusDirection.Right || direction == View.FocusDirection.Down) && right > visibleRectangleRight)
-                    {
-                        targetPosition = right - Size.Width;
-                    }
-                }
-                else
-                {
-                    if ((direction == View.FocusDirection.Up || direction == View.FocusDirection.Left) && top < visibleRectangleTop)
-                    {
-                        targetPosition = top;
-                    }
-                    else if ((direction == View.FocusDirection.Down || direction == View.FocusDirection.Right) && bottom > visibleRectangleBottom)
-                    {
-                        targetPosition = bottom - Size.Height;
-                    }
-                }
-
-                focusedView = nextFocusedView;
-                prevFocusedDataIndex = (nextFocusedView as RecyclerViewItem)?.Index ?? -1;
-
-                ScrollTo(targetPosition, true);
-            }
-            else
-            {
-                // If nextView is null, it means that we should move focus to outside of Control.
-                // Return FocusableView depending on direction.
-                switch (direction)
-                {
-                    case View.FocusDirection.Left:
-                        {
-                            nextFocusedView = LeftFocusableView;
-                            break;
-                        }
-                    case View.FocusDirection.Right:
-                        {
-                            nextFocusedView = RightFocusableView;
-                            break;
-                        }
-                    case View.FocusDirection.Up:
-                        {
-                            nextFocusedView = UpFocusableView;
-                            break;
-                        }
-                    case View.FocusDirection.Down:
-                        {
-                            nextFocusedView = DownFocusableView;
-                            break;
-                        }
-                }
-
-                if (nextFocusedView != null)
-                {
-                    focusedView = null;
-                }
-                else
-                {
-                    //If FocusableView doesn't exist, not move focus.
-                    nextFocusedView = focusedView;
-                }
-            }
-
-            return nextFocusedView;
-        }
-
         /// <summary>
         /// Update selected items list in multiple selection.
         /// </summary>
@@ -698,23 +773,26 @@ namespace Tizen.NUI.Components
         /// <since_tizen> 9 </since_tizen>
         public void UpdateSelectedItems(IList<object> newSelection)
         {
-            var oldSelection = new List<object>(SelectedItems);
+            if (SelectedItems != null)
+            {
+                var oldSelection = new List<object>(SelectedItems);
 
-            suppressSelectionChangeNotification = true;
+                suppressSelectionChangeNotification = true;
 
-            SelectedItems.Clear();
+                SelectedItems.Clear();
 
-            if (newSelection?.Count > 0)
-            {
-                for (int n = 0; n < newSelection.Count; n++)
+                if (newSelection?.Count > 0)
                 {
-                    SelectedItems.Add(newSelection[n]);
+                    for (int n = 0; n < newSelection.Count; n++)
+                    {
+                        SelectedItems.Add(newSelection[n]);
+                    }
                 }
-            }
 
-            suppressSelectionChangeNotification = false;
+                suppressSelectionChangeNotification = false;
 
-            SelectedItemsPropertyChanged(oldSelection, newSelection);
+                SelectedItemsPropertyChanged(oldSelection, newSelection);
+            }
         }
 
         /// <summary>
@@ -725,7 +803,11 @@ namespace Tizen.NUI.Components
         /// <since_tizen> 9 </since_tizen>
         public new void ScrollTo(float position, bool animate)
         {
-            if (ItemsLayouter == null) throw new Exception("Item Layouter must exist.");
+            if (ItemsLayouter == null)
+            {
+                throw new Exception("Item Layouter must exist.");
+            }
+
             if ((InternalItemSource == null) || needInitalizeLayouter)
             {
                 delayedScrollTo = true;
@@ -755,13 +837,18 @@ namespace Tizen.NUI.Components
         /// <since_tizen> 9 </since_tizen>
         public virtual void ScrollTo(int index, bool animate = false, ItemScrollTo align = ItemScrollTo.Nearest)
         {
-            if (ItemsLayouter == null) throw new Exception("Item Layouter must exist.");
+            if (ItemsLayouter == null)
+            {
+                throw new Exception("Item Layouter must exist.");
+            }
+
             if ((InternalItemSource == null) || needInitalizeLayouter)
             {
                 delayedIndexScrollTo = true;
                 delayedIndexScrollToParam = (index, animate, align);
                 return;
             }
+
             if (index < 0 || index >= InternalItemSource.Count)
             {
                 throw new Exception("index is out of boundary. index should be a value between (0, " + InternalItemSource.Count.ToString() + ").");
@@ -770,6 +857,7 @@ namespace Tizen.NUI.Components
             float scrollPos, curPos, curSize, curItemSize;
             (float x, float y) = ItemsLayouter.GetItemPosition(index);
             (float width, float height) = ItemsLayouter.GetItemSize(index);
+
             if (ScrollingDirection == Direction.Horizontal)
             {
                 scrollPos = x;
@@ -836,10 +924,21 @@ namespace Tizen.NUI.Components
                 string styleName = "Tizen.NUI.Compoenents." + (itemsLayouter is LinearLayouter? "LinearLayouter" : (itemsLayouter is GridLayouter ? "GridLayouter" : "ItemsLayouter"));
                 ViewStyle layouterStyle = ThemeManager.GetStyle(styleName);
                 if (layouterStyle != null)
+                {
                     itemsLayouter.Padding = new Extents(layouterStyle.Padding);
+                }
             }
         }
 
+        /// <summary>
+        /// Initialize AT-SPI object.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public override void OnInitialize()
+        {
+            base.OnInitialize();
+            AccessibilityRole = Role.List;
+        }
 
         /// <summary>
         /// Scroll to specified item
@@ -876,6 +975,7 @@ namespace Tizen.NUI.Components
         }
 
         // Realize and Decorate the item.
+
         internal override RecyclerViewItem RealizeItem(int index)
         {
             RecyclerViewItem item;
@@ -896,59 +996,21 @@ namespace Tizen.NUI.Components
                 var context = InternalItemSource.GetItem(index);
                 if (InternalItemSource.IsGroupHeader(index))
                 {
-                    DataTemplate templ = (groupHeaderTemplate as DataTemplateSelector)?.SelectDataTemplate(context, this) ?? groupHeaderTemplate;
-
-                    RecyclerViewItem groupHeader = PopRecycleGroupCache(templ, true);
-                    if (groupHeader == null)
-                    {
-                        groupHeader = (RecyclerViewItem)DataTemplateExtensions.CreateContent(groupHeaderTemplate, context, this);
-
-                        groupHeader.Template = templ;
-                        groupHeader.isGroupHeader = true;
-                        groupHeader.isGroupFooter = false;
-                        ContentContainer.Add(groupHeader);
-                    }
-
-                    if (groupHeader != null)
-                    {
-                        groupHeader.ParentItemsView = this;
-                        groupHeader.Index = index;
-                        groupHeader.ParentGroup = context;
-                        groupHeader.BindingContext = context;
-                    }
-                    //group selection?
-                    item = groupHeader;
+                    item = RealizeGroupHeader(index, context);
                 }
                 else if (InternalItemSource.IsGroupFooter(index))
                 {
-                    DataTemplate templ = (groupFooterTemplate as DataTemplateSelector)?.SelectDataTemplate(context, this) ?? groupFooterTemplate;
-
-                    RecyclerViewItem groupFooter = PopRecycleGroupCache(templ, false);
-                    if (groupFooter == null)
-                    {
-                        groupFooter = (RecyclerViewItem)DataTemplateExtensions.CreateContent(groupFooterTemplate, context, this);
 
-                        groupFooter.Template = templ;
-                        groupFooter.isGroupHeader = false;
-                        groupFooter.isGroupFooter = true;
-                        ContentContainer.Add(groupFooter);
-                    }
-
-                    if (groupFooter != null)
-                    {
-                        groupFooter.ParentItemsView = this;
-                        groupFooter.Index = index;
-                        groupFooter.ParentGroup = context;
-                        groupFooter.BindingContext = context;
-                    }
                     //group selection?
-                    item = groupFooter;
+                    item = RealizeGroupFooter(index, context);
                 }
                 else
                 {
                     item = base.RealizeItem(index);
                     if (item == null)
+                    {
                         throw new Exception("Item realize failed by Null content return.");
+                    }
                     item.ParentGroup = InternalItemSource.GetGroupParent(index);
                 }
             }
@@ -986,7 +1048,11 @@ namespace Tizen.NUI.Components
         // Unrealize and caching the item.
         internal override void UnrealizeItem(RecyclerViewItem item, bool recycle = true)
         {
-            if (item == null) return;
+            if (item == null)
+            {
+                return;
+            }
+
             if (item == Header)
             {
                 item?.Hide();
@@ -997,18 +1063,21 @@ namespace Tizen.NUI.Components
                 item.Hide();
                 return;
             }
+
             if (item.isGroupHeader || item.isGroupFooter)
             {
                 item.Index = -1;
                 item.ParentItemsView = null;
-                item.BindingContext = null; 
+                item.BindingContext = null;
                 item.IsPressed = false;
                 item.IsSelected = false;
                 item.IsEnabled = true;
                 item.UpdateState();
                 //item.Relayout -= OnItemRelayout;
                 if (!recycle || !PushRecycleGroupCache(item))
+                {
                     Utility.Dispose(item);
+                }
                 return;
             }
 
@@ -1027,11 +1096,17 @@ namespace Tizen.NUI.Components
                 if (item.BindingContext == null) continue;
                 if (newSelection.Contains(item.BindingContext))
                 {
-                    if (!item.IsSelected) item.IsSelected = true;
+                    if (!item.IsSelected)
+                    {
+                        item.IsSelected = true;
+                    }
                 }
                 else
                 {
-                    if (item.IsSelected) item.IsSelected = false;
+                    if (item.IsSelected)
+                    {
+                        item.IsSelected = false;
+                    }
                 }
             }
             SelectionPropertyChanged(this, new SelectionChangedEventArgs(oldSelection, newSelection));
@@ -1133,7 +1208,7 @@ namespace Tizen.NUI.Components
                 groupHeaderTemplate = null;
                 groupFooterTemplate = null;
 
-                if (selectedItem != null) 
+                if (selectedItem != null)
                 {
                     selectedItem = null;
                 }
@@ -1169,11 +1244,11 @@ namespace Tizen.NUI.Components
             colView.OnSelectionChanged(args);
         }
 
-        private static object CoerceSelectedItems(BindableObject bindable, object value)
+        private static object CoerceSelectedItems(CollectionView colView, object value)
         {
             if (value == null)
             {
-                return new SelectionList((CollectionView)bindable);
+                return new SelectionList(colView);
             }
 
             if (value is SelectionList)
@@ -1181,13 +1256,11 @@ namespace Tizen.NUI.Components
                 return value;
             }
 
-            return new SelectionList((CollectionView)bindable, value as IList<object>);
+            return new SelectionList(colView, value as IList<object>);
         }
 
-        private static void SelectionModePropertyChanged(BindableObject bindable, object oldValue, object newValue)
+        private static void SelectionModePropertyChanged(CollectionView colView, object oldValue, object newValue)
         {
-            var colView = (CollectionView)bindable;
-
             var oldMode = (ItemSelectionMode)oldValue;
             var newMode = (ItemSelectionMode)newValue;
 
@@ -1237,31 +1310,40 @@ namespace Tizen.NUI.Components
             SelectionPropertyChanged(colView, args);
         }
 
-        private void Init()
+        private void ReinitializeLayout()
         {
-            if (ItemsSource == null) return;
-            if (ItemsLayouter == null) return;
-            if (ItemTemplate == null) return;
-
-            if (disposed) return;
-            if (needInitalizeLayouter)
+            if (ItemsSource == null || ItemsLayouter == null || ItemTemplate == null)
             {
-                if (InternalItemSource == null) return;
+                return;
+            }
 
-                InternalItemSource.HasHeader = (header != null);
-                InternalItemSource.HasFooter = (footer != null);
+            if (disposed)
+            {
+                return;
             }
 
-            if (!wasRelayouted) return;
+            if (!wasRelayouted)
+            {
+                return;
+            }
 
             if (needInitalizeLayouter)
             {
+                if (InternalItemSource == null)
+                {
+                    return;
+                }
+
+                InternalItemSource.HasHeader = (header != null);
+                InternalItemSource.HasFooter = (footer != null);
+
                 itemsLayouter.Clear();
                 ClearCache();
 
                 ItemsLayouter.Initialize(this);
                 needInitalizeLayouter = false;
             }
+
             ItemsLayouter.RequestLayout(0.0f, true);
 
             if (delayedScrollTo)
@@ -1278,19 +1360,26 @@ namespace Tizen.NUI.Components
 
             if (ScrollingDirection == Direction.Horizontal)
             {
-                ContentContainer.SizeWidth = ItemsLayouter.CalculateLayoutOrientationSize();
+                ContentContainer.SizeWidth = (float)ItemsLayouter?.CalculateLayoutOrientationSize();
             }
             else
             {
-                ContentContainer.SizeHeight = ItemsLayouter.CalculateLayoutOrientationSize();
+                ContentContainer.SizeHeight = (float)ItemsLayouter?.CalculateLayoutOrientationSize();
             }
         }
 
         private bool PushRecycleGroupCache(RecyclerViewItem item)
         {
-            if (item == null) throw new ArgumentNullException(nameof(item));
-            if (RecycleCache.Count >= 20) return false;
-            if (item.Template == null) return false;
+            if (item == null)
+            {
+                throw new ArgumentNullException(nameof(item));
+            }
+
+            if  (item.Template == null || RecycleCache.Count >= 20)
+            {
+                return false;
+            }
+
             if (item.isGroupHeader)
             {
                 recycleGroupHeaderCache.Add(item);
@@ -1299,9 +1388,14 @@ namespace Tizen.NUI.Components
             {
                 recycleGroupFooterCache.Add(item);
             }
-            else return false;
+            else
+            {
+                return false;
+            }
+
             item.Hide();
             item.Index = -1;
+
             return true;
         }
 
@@ -1313,7 +1407,10 @@ namespace Tizen.NUI.Components
             for (int i = 0; i < Cache.Count; i++)
             {
                 viewItem = Cache[i];
-                if (Template == viewItem.Template) break;
+                if (Template == viewItem.Template)
+                {
+                    break;
+                }
             }
 
             if (viewItem != null)
@@ -1321,8 +1418,75 @@ namespace Tizen.NUI.Components
                 Cache.Remove(viewItem);
                 viewItem.Show();
             }
+
             return viewItem;
         }
+
+        private RecyclerViewItem RealizeGroupHeader(int index, object context)
+        {
+            DataTemplate templ = (groupHeaderTemplate as DataTemplateSelector)?.SelectDataTemplate(context, this) ?? groupHeaderTemplate;
+
+            RecyclerViewItem groupHeader = PopRecycleGroupCache(templ, true);
+
+            if (groupHeader == null)
+            {
+                groupHeader = DataTemplateExtensions.CreateContent(groupHeaderTemplate, context, this) as RecyclerViewItem;
+                if (groupHeader == null)
+                {
+                    return null;
+                }
+
+                groupHeader.Template = templ;
+                groupHeader.isGroupHeader = true;
+                groupHeader.isGroupFooter = false;
+                ContentContainer.Add(groupHeader);
+            }
+
+            if (groupHeader != null)
+            {
+                groupHeader.ParentItemsView = this;
+                groupHeader.Index = index;
+                groupHeader.ParentGroup = context;
+                groupHeader.BindingContext = context;
+
+                return groupHeader;
+            }
+
+            return null;
+        }
+
+        private RecyclerViewItem RealizeGroupFooter(int index, object context)
+        {
+            DataTemplate templ = (groupFooterTemplate as DataTemplateSelector)?.SelectDataTemplate(context, this) ?? groupFooterTemplate;
+
+            RecyclerViewItem groupFooter = PopRecycleGroupCache(templ, false);
+
+            if (groupFooter == null)
+            {
+                groupFooter = DataTemplateExtensions.CreateContent(groupFooterTemplate, context, this) as RecyclerViewItem;
+                if (groupFooter == null)
+                {
+                    return null;
+                }
+
+                groupFooter.Template = templ;
+                groupFooter.isGroupHeader = false;
+                groupFooter.isGroupFooter = true;
+                ContentContainer.Add(groupFooter);
+            }
+
+            if (groupFooter != null)
+            {
+                groupFooter.ParentItemsView = this;
+                groupFooter.Index = index;
+                groupFooter.ParentGroup = context;
+                groupFooter.BindingContext = context;
+                return groupFooter;
+            }
+
+            return null;
+        }
+
         private void CollectionChanged(object sender, NotifyCollectionChangedEventArgs args)
         {
             switch (args.Action)
@@ -1337,7 +1501,7 @@ namespace Tizen.NUI.Components
                         {
                             selectedItem = null;
                         }
-                        
+
                         if (selectedItems != null)
                         {
                             foreach (object removed in args.OldItems)