Как избежать неправильного повторного использования пользовательских ячеек в MvxGridView?

  1. У меня есть страница приложения Android (на фрагменте) с MvxGridView с таким макетом:

    <?xml version = "1.0" encoding = "utf-8"?>
    <LinearLayout xmlns:android = "http://schemas.android.com/apk/res/android"
         xmlns:local = "http://schemas.android.com/apk/res-auto"
         android:orientation = "vertical"
         android:layout_width = "match_parent"
         android:layout_height = "match_parent">
    
    <MvxGridView
        android:layout_width = "match_parent"
        android:layout_height = "match_parent"
        android:background = "@color/white"
        android:numColumns = "1"
        android:horizontalSpacing = "0dp"
        android:verticalSpacing = "0dp"
        local:MvxBind = "ItemsSource DayGraphsItems"
        local:MvxItemTemplate = "@layout/day_graph_item" />
    </LinearLayout>
    
  2. У меня есть собственный вид для рисования графика:

    public class GraphView : View
    {
        Paint mPaint;
        Bitmap mBitmap;
        Canvas mCanvas;
        Path mPath;
        Paint mBitmapPaint;
    
        public List<string> Data { get; set; }
    
        public GraphView(Context context, Android.Util.IAttributeSet attributeSet) : base(context)
        {
            mPaint = new Paint();
            mPaint.AntiAlias = true;
            mPaint.Dither = true;
            mPaint.SetARGB(0xFF, 0xFF, 0xFF, 0xFF);
            mPaint.SetStyle(Paint.Style.FillAndStroke);
            mPaint.StrokeJoin = Paint.Join.Round;
            mPaint.StrokeCap = Paint.Cap.Round;
            mPaint.StrokeWidth = 1;
            mPaint.TextSize = 24;
    
            mPath = new Path();
            mBitmapPaint = new Paint();
           mBitmapPaint.SetARGB(0xFF, 0xFF, 0xff, 0xff);
       }
    
       protected override void OnSizeChanged(int w, int h, int oldw, int oldh)
       {
            if (w > 0 && h > 0)
            {
                mBitmap = Bitmap.CreateBitmap(w, h, Bitmap.Config.Argb8888);
                mCanvas = new Canvas(mBitmap);
    
                _canvasHeight = h;
                _canvasWidth = w;
    
                DrawTheGraph(Data);
            }
        }
    
        public override void Draw(Canvas canvas)
        {
            canvas.DrawBitmap(mBitmap, 0, 0, mBitmapPaint);
            canvas.DrawPath(mPath, mPaint);
            canvas.Restore();
        }
    
        private void DrawTheGraph(List<string> data)
        {
           // here is drawing of the graph which works well
        }
    }
    
  3. У меня есть кастомная привязка

    public class GraphCustomBinding : MvxConvertingTargetBinding
    {
    
        public static string Name = "GraphCustom";
    
        public GraphCustomBinding(GraphView target) : base(target)
        {
        }
    
        protected override void SetValueImpl(object target, object value)
        {
            var data = new List<string>();
            data = (List<string>)value;
    
            var targetGraphView = (GraphView)target;
            targetGraphView.Data = data;
        }
    
        public override Type TargetType
        {
             get { return typeof(GraphView); }
        }
    }
    
  4. Привязка правильно прописана в настройке.

  5. У меня есть макет элемента для элементов списка DayGraphsItems

    <?xml version = "1.0" encoding = "utf-8"?>
    <LinearLayout xmlns:android = "http://schemas.android.com/apk/res/android"
        xmlns:local = "http://schemas.android.com/apk/res-auto"
        android:orientation = "vertical"
        android:layout_width = "match_parent"
        android:layout_height = "match_parent"
        android:paddingLeft = "15dp"
        android:paddingRight = "15dp"
        android:paddingTop = "15dp"
        android:paddingBottom = "15dp">
    <TextView
        android:layout_width = "match_parent"
        android:layout_height = "wrap_content"
        android:gravity = "center_vertical|center_horizontal"
        style = "@style/TextViewCurrentConditionsHeader"
        local:MvxBind = "Text Title" />
    <Pogoda.Droid.GraphView
        android:layout_width = "match_parent"
        android:layout_height = "300dp"
        android:padding = "5dp"
        local:MvxBind = "GraphCustom Data, Mode=TwoWay" />
    </LinearLayout>
    

Обновлено:

  1. DayGraphsItems - это список DayGraphItem, который представлен следующим образом:

    public class DayGraphItem
    {
        public int Id { get; set; }
    
        public string Title { get; set; }
    
        public List<string> Data { get; set; }
    }
    
  2. Вид находится на фрагменте:

    [Register("pogoda.droid.DayGraphsFragment")]
    public class DayGraphsFragment : BaseFragment<DayGraphsViewModel>
    {
        public const string TAG = "DayGraphsFragmentTag";
    
        public override string UniqueImmutableCacheTag
        {
            get
            {
                return TAG;
            }
        }
    
        public override Android.Views.View OnCreateView(Android.Views.LayoutInflater inflater, Android.Views.ViewGroup container, Android.OS.Bundle savedInstanceState)
        {
            base.OnCreateView(inflater, container, savedInstanceState);
            return this.BindingInflate(Resource.Layout.day_graphs_layout, null);
        }
    }
    

Проблема: Графики нарисованы правильно, но в случае, когда на экране больше ячеек, чем может быть отображено сразу, после прокрутки вниз я вижу ячейки, которые были нарисованы раньше, а не новые (похоже, используются повторно).

ВОПРОС: Как этого избежать и отображать свежие графики вместо этих "прокрученных сверху"?

какой тип DayGraphsItems в вашей ViewModel? Кстати, ваш GraphCustom должен быть Mode=OneWay, потому что эта реализация настраиваемой привязки, которая не запускает изменения из представления в модель просмотра

fmaccaroni 02.05.2018 20:19

Вы правы - это должен быть Mode=OneWay, но это не является причиной проблем. Завершил вопрос по вашему запросу, добавив пункт 6 - есть определение списка товаров.

Radosław Rudnicki 04.05.2018 14:44

Чтобы увидеть, проблема ли это в элементе управления, модели просмотра или между ними, я бы заменил ваш MvxGridView на MvxRecyclerView, чтобы увидеть, продолжается ли поведение

fmaccaroni 04.05.2018 14:50

добавил также пункт 7 с фрагментом. спасибо за ответы. проверим с MvxRecyclerView. сообщу вам :)

Radosław Rudnicki 04.05.2018 14:56

Я думаю, что нужно привлечь какого-то адатера, но понятия не имею, как это реализовать в моем случае

Radosław Rudnicki 04.05.2018 14:59

вы можете использовать MvxRecyclerView напрямую, не указывая адаптер; это просто проверить, одинаково ли поведение

fmaccaroni 04.05.2018 15:09

Да, такая же проблема при использовании MvxRecyclerView

Radosław Rudnicki 04.05.2018 16:29
0
7
68
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Решение, которое работает для меня, это

Создайте EnhancedMvxListView и замените MvxGridView, используя его в пункте 1.

    public class EnhancedMvxListView : MvxListView
    {
        public EnhancedMvxListView(Context context, IAttributeSet attrs) : base(context, attrs, new EnhancedMvxAdapter(context))
        { 
        }

        public EnhancedMvxListView(Context context, IAttributeSet attrs, IMvxAdapter adapter) : base(context, attrs, new EnhancedMvxAdapter(context))
        { 
        }
    }

где EnhancedMvxAdapter следующий

public class EnhancedMvxAdapter : MvxAdapterWithChangedEvent
{
    public EnhancedMvxAdapter(Context context) : base(context)
    {
    }

    protected override View GetBindableView(View convertView, object dataContext, ViewGroup parent, int templateId)
    {
        templateId = GetTemplateId(dataContext);

        var view = base.GetBindableView(convertView, dataContext, parent, templateId);

        var context = dataContext as DayGraphItem;

        view.FindViewById<TextView>(Resource.Id.graphTitle).Text = context.Title;
        view.FindViewById<GraphView>(Resource.Id.graphDrawing).Data = context.Data;

        return view;
    }

    private int GetTemplateId(object data)
    {
        return Resource.Layout.day_graph_item;
    }
}

И, наконец, в файле в пункте 2. Я заменил

    public List<string> Data { get; set; }    

с участием

    List<string> _data;
    public List<string> Data
    {
        get
        {
            return _data;
        }
        set
        {
            if (value != null && value != _data)
            {
                _data = value;

                if ((int)_canvasWidth == 0 || (int)_canvasHeight == 0)
                    return;

                mBitmap = Bitmap.CreateBitmap((int)_canvasWidth, (int)_canvasHeight, Bitmap.Config.Argb8888);
                mCanvas = new Canvas(mBitmap);

                DrawTheGraph(Data);
            }
        }
    } 

Другие вопросы по теме