user3824367
user3824367

Reputation: 11

Problems with customization Xamarin.Forms.ListView

Problems in customization Xamarin.Forms.ListView

Task: I need to implement a control for displaying items in GridView as on android.

The essence of the problem and attempt to implement it: I am created the class GridListBox inherated from GridListBox Xamarin.Forms.ListView. The next i am created GridListBoxRenderer take for example Xamarin.Forms.Platform.Android.ListViewRenderer

My GridListBox:

public class GridListBox : ListView
    {
        public static readonly BindableProperty ColumnCountProperty = BindableProperty.Create<GridListBox, int>(r => r.ColumnCount, 2);
        public int ColumnCount
        {
            get { return (int)GetValue(ColumnCountProperty); }
            set { SetValue(ColumnCountProperty, value); }
        }

        public static readonly BindableProperty HorizontalSpacingProperty = BindableProperty.Create<GridListBox, int>(r => r.HorizontalSpacing, 5);
        public int HorizontalSpacing
        {
            get { return (int)GetValue(HorizontalSpacingProperty); }
            set { SetValue(HorizontalSpacingProperty, value); }
        }

        public static readonly BindableProperty VerticalSpacingProperty = BindableProperty.Create<GridListBox, int>(r => r.VerticalSpacing, 5);
        public int VerticalSpacing
        {
            get { return (int)GetValue(VerticalSpacingProperty); }
            set { SetValue(VerticalSpacingProperty, value); }
        }
    }

Renderer for GridListBox:

public class GridListBoxRenderer:NativeRenderer
    {
        private Cell cellFocused;
        protected override void OnModelChanged(VisualElement oldModel, VisualElement newModel)
        {
            base.OnModelChanged(oldModel, newModel);

            var realListView = (GridView)Control;
            if (realListView == null)
            {
                realListView = new GridView(Context);
                SetNativeControl((View)realListView);
            }
            cellFocused = (Cell)null;
            realListView.Focusable = false;
            realListView.DescendantFocusability = DescendantFocusability.AfterDescendants;
            realListView.OnFocusChangeListener = (IOnFocusChangeListener)this;
            realListView.SetNumColumns(((Controls.GridListBox) newModel).ColumnCount);
            realListView.SetHorizontalSpacing(((Controls.GridListBox)newModel).HorizontalSpacing);
            realListView.SetVerticalSpacing(((Controls.GridListBox)newModel).VerticalSpacing);
            realListView.Adapter = new GridViewAdapter(Context, realListView, (Controls.GridListBox)newModel);
        }

        public override Size MinimumSize()
        {
            return new Size(40.0, 40.0);
        }
    }

And then the fun began: Implementation GridViewAdapter is easy if take for example Xamarin.Forms.Platform.Android.ListViewAdapter (access as Internal). To implement the public BaseAdapter.GetView (int position, View convertView, ViewGroup parent) with use ItemTemplate needs access to Xamarin.Forms.ListView.TemplatedItems but it's Internal ...

P.S. How do developers from Xamarin planned to enable developers to customize Xamarin.Forms If most of the properties with internal access ...?

P.P.S. Similar difficulties have with customize the Xamarin.Forms.Page. The Xamarin.Forms.Page.InternalChildren property is internal

Upvotes: 0

Views: 2091

Answers (1)

user3824367
user3824367

Reputation: 11

Resolving this issue is to use Reflection to access the internalization property

 public GridViewAdapter(Context context, GridView realListView, GridListBox gridListView)
            {
                _context = context;
                _realListView = realListView;
                _gridListView = gridListView;

                var info = _gridListView.GetType().GetProperty("TemplatedItems", BindingFlags.Instance |
                                BindingFlags.NonPublic |
                                BindingFlags.Public);
                var item = info.GetValue(_gridListView);

                _templatedItemsList = item as IList;
                _templatedItemsINCC = item as INotifyCollectionChanged;

                _templatedItemsINCC.CollectionChanged += _templatedItemsINCC_CollectionChanged;
            }

Upvotes: 1

Related Questions