博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
UWP FillRowViewPanel
阅读量:6603 次
发布时间:2019-06-24

本文共 5932 字,大约阅读时间需要 19 分钟。

最近有童鞋有这种需求,说实话我不知道这个Panel怎么起名字。

效果连接https://tuchong.com/tags/风光/

下面是我做成的效果,可以规定每个Row的Items个数

2个

3个

4个

代码在:

下面我来说一下我的思路

其实很早之前就写过这种可变大小的,但这次的跟这个需求有点变化,这个每一行个数一定,大小根据图片的大小进行填充。

微软默认的VariableSizedWrapGrid和Toolikt里面的StaggeredPanel都会导致ListView失去一些特性(虚拟化,增量加载)

之前做另一种。其实现在这个差不多。就是ListViewItem 就是每一行,那么每一行里面相当于一个水平的ListView。

我只需要做一个Panel来布局填充行就可以了。。垂直上面还是ListView自带的效果

除此之后,还需要一个数据源来把 一维的数据改为了 二维的(根据每一行的个数)

直接上代码:

FillRowViewSource这个类是把一个 一维的数据源改为了 二维的。主要方法是UpdateRowItems根据RowItemsCount把集合分割

private void UpdateRowItems()        {            if (sourceList == null)            {                return;            }            int i = 0;            var rowItems = sourceList.Skip(i * RowItemsCount).Take(RowItemsCount);            while (rowItems != null && rowItems.Count() != 0)            {                var rowItemsCount = rowItems.Count();                var item = this.ElementAtOrDefault(i);                if (item == null)                {                    item = new ObservableCollection
(); this.Insert(i, item); } for (int j = 0; j < rowItemsCount; j++) { var rowItem = rowItems.ElementAt(j); var temp = item.ElementAtOrDefault(j); if (temp==null || !temp.Equals(rowItem)) { item.Insert(j, rowItem); } } while (item.Count > rowItemsCount) { item.RemoveAt(item.Count - 1); } i++; rowItems = sourceList.Skip(i * RowItemsCount).Take(RowItemsCount); } var rowCount = sourceList.Count / RowItemsCount + 1; while (this.Count > rowCount) { this.RemoveAt(this.Count - 1); } }
View Code

FillRowViewPanel 最早的时候希望使用item.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));方式来获得每个元素的大小,但是像Image这些控件不是开始就有大小的,需要等待图片加载完毕,而且每个Item都进行Measure的话。性能也不佳。

最后还是按照老控件的方式IResizable 写了个接口。绑定的数据源对象必须继承这个。你需要告诉我你的每个Item的大小尺寸。这样计算起来就方便多了而且有效多了

public class FillRowViewPanel : Panel    {        public int MinRowItemsCount        {            get { return (int)GetValue(MinRowItemsCountProperty); }            set { SetValue(MinRowItemsCountProperty, value); }        }        // Using a DependencyProperty as the backing store for MinRowItemsCount.  This enables animation, styling, binding, etc...        public static readonly DependencyProperty MinRowItemsCountProperty =            DependencyProperty.Register("MinRowItemsCount", typeof(int), typeof(FillRowViewPanel), new PropertyMetadata(0));        protected override Size MeasureOverride(Size availableSize)        {            var size = base.MeasureOverride(availableSize);            return size;        }        protected override Size ArrangeOverride(Size finalSize)        {            double childrenWidth = 0;            //double maxheight = double.MinValue;            foreach (var item in Children)            {                if (item is ContentControl cc && cc.Content is IResizable iResizable)                {                    //item.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));                    var elementSize = iResizable;                    var width = elementSize.Width * finalSize.Height / elementSize.Height;                    //maxheight = Math.Max(elementSize.Height, maxheight);                    childrenWidth += width;                }            }            double ratio = childrenWidth / finalSize.Width;            double x = 0;            var count = Children.Count;            foreach (var item in Children)            {                if (item is ContentControl cc && cc.Content is IResizable iResizable)                {                    var elementSize = iResizable;                    var width = elementSize.Width * finalSize.Height / elementSize.Height;                    //if children count is less than MinRowItemsCount and chidren total width less than finalwidth                    //it don't need to stretch children                    if (count < MinRowItemsCount && ratio < 1)                    {                        //to nothing                    }                    else                    {                        width /= ratio;                    }                    var rect = new Rect(x, 0, width, finalSize.Height);                    item.Measure(new Size(rect.Width, finalSize.Height));                    item.Arrange(rect);                    x += width;                }            }            return base.ArrangeOverride(finalSize);        }    }
View Code

在Sample页面

原理就是Listview的Item其实是个ListView。而做为Item的ListView的Panel是FillRowViewPanel

记住给FillRowViewPanel的高度进行设置。相当于每个元素的高度

View Code

在整个ListViewSizechanged的时候我们再根据自己的需求调整RowItemsCount。

private void FillRowView_SizeChanged(object sender, SizeChangedEventArgs e)        {            if (e.NewSize.Width < 600)            {                source.UpdateRowItemsCount(2);            }            else if (e.NewSize.Width >= 600 && e.NewSize.Width < 900)            {                source.UpdateRowItemsCount(3);            }            else            {                source.UpdateRowItemsCount(4);            }        }
View Code

整个就差不多这样了。做的比较简单。一些东西也没有全部去考虑。比如SourceList_CollectionChanged的时候。只考虑了Reset这种方式。

算是比较针对这个需求做的东东吧,如果有其他需求。可以提出来。大家一起撸撸。

老规矩 开源有益:

 

转载于:https://www.cnblogs.com/FaDeKongJian/p/9376569.html

你可能感兴趣的文章
more adj/adv than as well as prefer to
查看>>
pitfall fields
查看>>
Hadoop实战读书笔记(3)
查看>>
策略模式
查看>>
2012-2013 微软商业智能大调研分析报告
查看>>
iOS7设计规范分享:UI设计基础
查看>>
徐元杰:“淘”里“淘”外,简单营销
查看>>
国内外SNS比较分析
查看>>
iOS Image Filters
查看>>
Dsoframer实现文档在线浏览功能
查看>>
【图解AI】什么是语义分割、实例分割、全景分割
查看>>
调整PHPStorm中文件修改后标签和文件名的颜色与背景色
查看>>
devise登陆页不使用application模版
查看>>
微信小程序,用户私密信息解密
查看>>
android程序在下载文件时报java.io.EOFException
查看>>
swoole项目思维转换 -- 前篇
查看>>
Spring事务的传播属性和隔离级别
查看>>
SpringBoot之WebSocket和SSE
查看>>
在zsh下使用tmux会自动变更窗口名称的问题
查看>>
cpuidle_mediaroom
查看>>