Проблемы с настройкой Xamarin.Forms.ListView

Проблемы в настройке Xamarin.Forms.ListView

Задача: Мне нужно реализовать контрол для отображения элементов в GridView как на андроиде.

Суть проблемы и попытка ее реализации: Создаю класс GridListBox унаследованный от GridListBox Xamarin.Forms.ListView. В следующий раз я создал GridListBoxRenderer, например, Xamarin.Forms.Platform.Android.ListViewRenderer.

Мой 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); }
        }
    }

Рендерер для 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);
        }
    }

И тут началось самое интересное: реализация GridViewAdapter проста, если взять, например, Xamarin.Forms.Platform.Android.ListViewAdapter (доступ как Internal). Для реализации общедоступного BaseAdapter.GetView (int position, View convertView, ViewGroup parent) с использованием ItemTemplate требуется доступ к Xamarin.Forms.ListView.TemplatedItems, но он является внутренним...

P.S. Как разработчики из Xamarin планировали дать возможность разработчикам настраивать Xamarin.Forms, если большинство свойств с внутренним доступом...?

П.П.С. Аналогичные трудности возникают при настройке Xamarin.Forms.Page. Свойство Xamarin.Forms.Page.InternalChildren является внутренним


person user3824367    schedule 10.07.2014    source источник
comment
Расскажи мне об этом! код Xamarin.Forms замусорен внутренними вещами и жестко запрограммированными ограничениями (например, только жесты касания!)   -  person Sten Petrov    schedule 15.07.2014
comment
Один из способов обойти их внутренние дела — просто скопировать и вставить код из их сборки в вашу — по большей части это работает.   -  person Sten Petrov    schedule 15.07.2014


Ответы (1)


Решение этой проблемы заключается в использовании Reflection для доступа к свойству интернализации.

 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;
            }
person user3824367    schedule 15.07.2014