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;
        }
    }

可以看到这个类的构造

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

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

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

时间: 2025-01-02 19:08:54

UWP VirtualizedVariableSizedGridView 支持可虚拟化可变大小Item的View(一)的相关文章

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

上篇UWP VirtualizedVariableSizedGridView 支持可虚拟化可变大小Item的View(一) 讲到该控件的需要和设计过程. 这篇讲讲开发过程中一些重要问题解决. 1.支持ISupportIncrementalLoading,实现HasMoreItems属性和LoadMoreItemsAsync方法 因为我们上篇里面讲过,需要把源数据分成一个一个的Group作为GirdView的源, 所以LoadMoreItemsAsync方法里面我做了以下的实现: public I

NET Framework 4.5新特性 (三)64位平台支持大于2 GB大小的数组

64位平台.NET Framework数组限制不能超过2GB大小.这种限制对于需要使用到大型矩阵和向量计算的工作人员来说,是一个非常大问题. 无论RAM容量有多大有多少,一旦你使用大型矩阵和向量计算工作的时候,经常会抛出一个System.OutOfMemoryException异常,如下图所示: 参考程序 class Program { private static void Main(string[] args) { int arrysize = 150000000; var large=ne

【翻译自mos文章】怎么检查服务器主板BIOS支持的最大内存大小?

怎么检查服务器主板BIOS支持的最大内存大小? 来源于: How to check Maximum Supported Memory by Motherboard Bios (文档 ID 1680534.1) 适用于: Linux OS - Version Oracle Linux 5.0 to Oracle Linux 6.5 [Release OL5 to Ol6U5] Linux x86-64 Linux x86 目标: 获得服务器主板BIOS支持的最大内存大小 解决方案: 简单的dmid

让Proxmox VE支持嵌套虚拟化

目前公司的测试环境使用Proxmox VE(PVE),PVE虚拟出来的主机CPU默认不支持vmx,即不支持嵌套虚拟化,在虚拟机中使用egrep "vmx|svm" /proc/cpuinfo验证,无输出,那么如何让他支持呢?其实PVE的内核还是采用了KVM+Qemu的方式模拟,那么参照如何让KVM支持嵌套虚拟化的方法操作,开启nested即可 nested是一个可通过内核参数来启用的功能.它能够使一台虚拟机具有物理机CPU特性,支持vmx或者svm(AMD)硬件虚拟化.Proxmox

Xamarin.Forms 现已开启对 UWP 的支持

Xamarin.Forms 现已升级到 2.0.0.6482 , 正式开启了对 UWP 的支持. 要创建 UWP 项目, 必须是 VS2015, WIN8.1 下也可以, 但是只有 Windows 10 Mobile 的模拟器可用, Windows 10 的模拟器, 必须在 WIN 10 下. 以下简称 Xamarin.Forms 为 XF, Caliburn.Micro 为 CM 创建 XF支持的 UWP 项目 XF的项目模板, 当前没有加入 UWP , 需要手动创建 UWP 项目. 过程如下

WinSCP登陆服务器提示收到了太大的SFTP包 支持的最大包大小1024000B

前情回顾: 每次用rm都心惊胆战,于是5月7号晚上,找资料把rm替换为mv命令,模拟成了WINDOWS下面的回收站. 组里面有好几个人一起使用服务器,回收站的文件夹就设置到了每个用户起始目录下. 把每个用户的.bashrc修改了一下,一时心好,想提示登录的用户现在可以找回文件: 在每个用户的~/.bashrc中增加了一行: ? 1 echo "using the order ur +filename  to recover your file" 5月8号早上来实验室,大师姐给我说,不能

解决VMware下64位linux系统不支持全虚拟化(vmx)

一.前提: cpu支持Inter VT-X或AMD虚拟化技术,具体参考官网说明. 二.问题描述: 物理机下,vmware workstation能安装64位CentOS系统,处理器Inter i3 M390,且支持Inter VT-X虚拟化技术,物理机BIOS中已打开Inter虚拟化开关(自己找),既然能安装64位系统,说明物理机BIOS中支持虚拟化开关已打开. 半虚拟化为pae 全虚拟化为vmx(Inter).svm(AMD) # uname -r 2.6.32-358.el6.x86_64

可变大小结构体如何定义详解

一.背景 工作中,在通信协议中常常看到TLV格式数据,不同的type id对应的字符串长度大小不一样.那么该怎么去定义一个结构体去管理这些数据呢?怎么去定义一种可变大小的结构体?本文将讲解如何定义可变大小结构体. 二.定义可变大小结构体 1.方法一:使用指针 1 typedef struct _S_HB_TIME_REPORT_INFO 2 { 3 uint16_t msg_id; 4 uint16_t msg_buf_len; 5 char *p_msg_buf; 6 }__attribute

intel或amd,vmware开启支持kvm虚拟化

vmware --> 左侧选择具体的计算机 --> 右键选择 设置 --> 处理器 --> 把 虚拟化 Intel VT-x/EPT 或 AMD-V.RVI(V) 勾上 --> 重启虚拟机. [[email protected] ~]# egrep "lm|vmx|svm" /proc/cpuinfo 如果匹配到内容即表示已支持kvm虚拟化. 原文地址:http://blog.51cto.com/12555197/2309687