• UWP VirtualizedVariableSizedGridView 支持可虚拟化可变大小Item的View(一)


    Boss的需要时这样的,Item是可变大小的,同时根据不同的Window size,来确定Item的结构和大小
    Window 小的时候是

    大的时候是这样的:

    当然这size变化的过程中也允许其他结构,我这里只是举了最大和最小时候的样子。

    当拿到需求的时候,相信大家肯定第一想到的是,将GirdView的ItemsPanel改成VariableSizedWrapGrid。
    VariableSizedWrapGrid是怎么样用的,不知道的童鞋点击先行脑补下.官方文档  diederik的sample

    嗯,效果就这样的,差不多。。。是这样的吗??

    仔细的朋友可以看到了这段话:
    The content of a VariableSizedWrapGrid is not virtualized. This can reduce performance when you work with large data sets. For more info, see Optimize ListView and GridView.

    哦,no。这个东西不支持虚拟化。。

    Google了下,嗯。各种网上问的,但是没有解决办法。想想也是,这种结构,是很难计算出Items的总高度或者总宽度的。

    本着我不下地狱谁下地狱的原则,既然没人搞出来,就让我来造福大众吧。。。我疯狂的上网搜索,自己也想过一些办法,但都被自己推倒了。(太软,易推倒)

    吃晚饭的时候突然灵光一现,嗯,想出了下面的结构:

    ListView的每个Item是个GridView,而将GirdView的ItemsPanel改成VariableSizedWrapGrid。

    自己写了个简单的sample,稍微搞了些,可行。

    数据结构应该是这样的:

    比如一共有150个Item,15个元素为一组作为每个GridView的源来组成可变大小结构。

    现在的问题来了,怎么样才能方便的把原始的数据结构转变为我想要的那种呢??

    方法是写一个IList 类来做这个分割。

    internal class RowAdapter<T> : IList<IEnumerable<T>>, ISupportIncrementalLoading
        {
            private readonly IList<T> items;
            public readonly int rowItemsCount;
    
            public IList<T> SourceList
            {
                get { return items; }
            }
    
            public RowAdapter(IList<T> sourceList, int rowItemsCount)
            {
                if (null == sourceList)
                    throw new ArgumentNullException("sourceList", "sourceList can not be null");
                if (rowItemsCount <= 0)
                    throw new ArgumentOutOfRangeException("rowItemsCount", "rowItemsCount should be more than one");
    
                // We require the source list to implement IList because we
                // need to know how many item there are
                items = sourceList;
                this.rowItemsCount = rowItemsCount;
    
            }
    
            #region IList<IEnumerable<T>> Members
    
            public int IndexOf(IEnumerable<T> item)
            {
                var realItem = item as RowObject<T>;
                if (null == realItem || !ReferenceEquals(realItem.Parent, this))
                    return -1;          // It does not belong to this collection
    
                Debug.Assert(0 == realItem.StartIndex % rowItemsCount, "RowObject item has a wierd index");
                return realItem.StartIndex / rowItemsCount;
            }
    
            public void Insert(int index, IEnumerable<T> item)
            {
                throw new NotSupportedException();
            }
    
            public IEnumerable<T> this[int index]
            {
                get
                {
                    if (index < 0 || index > Count)
                        return null;
    
                    return InternalGetRow(index);
                }
                set
                {
                    throw new NotSupportedException();
                }
            }
    
            public void RemoveAt(int index)
            {
                throw new NotSupportedException();
            }
    
            #endregion
    
            #region ICollection<IEnumerable<T>> Members
    
            public void Add(IEnumerable<T> item)
            {
                throw new NotSupportedException();
            }
    
            public bool Contains(IEnumerable<T> item)
            {
                var realItem = item as RowObject<T>;
                return null != realItem && object.ReferenceEquals(realItem.Parent, this);
            }
    
            public void CopyTo(IEnumerable<T>[] array, int arrayIndex)
            {
                // I haven't implemented this. It is easy to implement if you need it
                throw new NotImplementedException();
            }
    
            public bool Remove(IEnumerable<T> item)
            {
                throw new NotSupportedException();
            }
            public void Clear()
            {
                throw new NotSupportedException();
            }
    
            public int Count
            {
                get
                {
                    return (items.Count + (rowItemsCount - 1)) / rowItemsCount;
                }
            }
    
            public bool IsReadOnly
            {
                get { return true; }
            }
    
            public bool HasMoreItems
            {
                get
                {
                    if (items is ISupportIncrementalLoading)
                    {
                        return (items as ISupportIncrementalLoading).HasMoreItems;
                    }
                    return false;
                }
            }
    
            #endregion
    
            #region IEnumerable<IEnumerable<T>> Members
    
            public IEnumerator<IEnumerable<T>> GetEnumerator()
            {
                for (int i = 0; i < Count; ++i)
                {
                    yield return InternalGetRow(i);
                }
            }
    
            #endregion
    
            #region IEnumerable Members
    
            System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
            {
                return GetEnumerator();
            }
    
            #endregion
    
            private RowObject<T> InternalGetRow(int index)
            {
                return new RowObject<T>(this, index * rowItemsCount);
            }
    
            public IAsyncOperation<LoadMoreItemsResult> LoadMoreItemsAsync(uint count)
            {
                if (items is ISupportIncrementalLoading)
                {
                    IAsyncOperation<LoadMoreItemsResult> result = (items as ISupportIncrementalLoading).LoadMoreItemsAsync(count);
                    return result;
                }
    
                return null;
            }
        }
    View Code

    可以看到这个类的构造

    public RowAdapter(IList<T> sourceList, int rowItemsCount)

    sourceList就是源数据,而rowItemsCount就是每个GirdView里面源的个数。

    到这里我们就解决了,整个控件的大体思路以及源的处理,下一篇会讲讲该开发中一些重要问题的解决。
    有问题的朋友可以留言,或者查看GitHub源码

  • 相关阅读:
    0、前端页面的请求路径
    5、Spring事务
    4、Spring整合MyBatis
    2.3、Spring多配置文件
    2.2、基于注解的DI注入
    Rest语法,传入多个参数
    JS中 `=+` 是什么?
    Node.js 爬虫爬取电影信息
    JavaScript监听页面可见性(焦点)同时改变title的三种方法
    CSS 清除浮动的方法
  • 原文地址:https://www.cnblogs.com/FaDeKongJian/p/5577440.html
Copyright © 2020-2023  润新知