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

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

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

2个

3个

4个

代码在:GitHub

下面我来说一下我的思路

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

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

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

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

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

直接上代码:

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

        private void UpdateRowItems()
{
if (sourceList == null)
{
return;
}
int i = ;
var rowItems = sourceList.Skip(i * RowItemsCount).Take(RowItemsCount);
while (rowItems != null && rowItems.Count() != )
{
var rowItemsCount = rowItems.Count();
var item = this.ElementAtOrDefault(i);
if (item == null)
{
item = new ObservableCollection<T>();
this.Insert(i, item);
} for (int j = ; 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 - );
}
i++;
rowItems = sourceList.Skip(i * RowItemsCount).Take(RowItemsCount);
} var rowCount = sourceList.Count / RowItemsCount + ;
while (this.Count > rowCount)
{
this.RemoveAt(this.Count - );
} }

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()); protected override Size MeasureOverride(Size availableSize)
{
var size = base.MeasureOverride(availableSize);
return size;
} protected override Size ArrangeOverride(Size finalSize)
{
double childrenWidth = ;
//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 = ;
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 < )
{
//to nothing
}
else
{
width /= ratio;
} var rect = new Rect(x, , width, finalSize.Height);
item.Measure(new Size(rect.Width, finalSize.Height));
item.Arrange(rect);
x += width;
} }
return base.ArrangeOverride(finalSize);
}
}

在Sample页面

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

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

        <ct:PullToRefreshGrid RefreshThreshold=""  PullToRefresh="PullToRefreshGrid_PullToRefresh">
<ListView x:Name="FillRowView" SizeChanged="FillRowView_SizeChanged">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="Margin" Value=""/>
<Setter Property="Padding" Value=""/>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<ListView ScrollViewer.HorizontalScrollMode="Disabled" ItemsSource="{Binding}">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="Margin" Value=""/>
<Setter Property="Padding" Value=""/>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<ct:FillRowViewPanel x:Name="fillRowViewPanel" MinRowItemsCount="" Height=""/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<!--<msct:ImageEx Margin="" IsCacheEnabled="True" Source="{Binding ImageUrl}" Stretch="Fill"/>-->
<Image Margin="" Source="{Binding ImageUrl}" Stretch="Fill"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ct:PullToRefreshGrid>

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

         private void FillRowView_SizeChanged(object sender, SizeChangedEventArgs e)
{
if (e.NewSize.Width < )
{
source.UpdateRowItemsCount();
}
else if (e.NewSize.Width >= && e.NewSize.Width < )
{
source.UpdateRowItemsCount();
}
else
{
source.UpdateRowItemsCount();
}
}

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

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

老规矩 开源有益:Github

UWP FillRowViewPanel的更多相关文章

  1. UWP 律师查询 MVVM

    APP简介 律师查询是基于聚合数据的律师查询接口做的,这个接口目前处于停用状态,但是,由于我是之前申请的,所以,还可以用,应该是无法再申请了. 效果图 开发 一.HttpHelper 既然是请求接口的 ...

  2. 领域驱动和MVVM应用于UWP开发的一些思考

    领域驱动和MVVM应用于UWP开发的一些思考 0x00 起因 有段时间没写博客了,其实最近本来是根据梳理的MSDN上的资料(UWP开发目录整理)有条不紊的进行UWP学习的.学习中有了心得体会或遇到了问 ...

  3. UWP中实现自定义标题栏

    UWP中实现自定义标题栏 0x00 起因 在UWP开发中,有时候我们希望实现自定义标题栏,例如在标题栏中加入搜索框.按钮之类的控件.搜了下资料居然在一个日文网站找到了一篇介绍这个主题的文章: http ...

  4. UWP中新加的数据绑定方式x:Bind分析总结

    UWP中新加的数据绑定方式x:Bind分析总结 0x00 UWP中的x:Bind 由之前有过WPF开发经验,所以在学习UWP的时候直接省略了XAML.数据绑定等几个看着十分眼熟的主题.学习过程中倒是也 ...

  5. MVVM框架从WPF移植到UWP遇到的问题和解决方法

    MVVM框架从WPF移植到UWP遇到的问题和解决方法 0x00 起因 这几天开始学习UWP了,之前有WPF经验,所以总体感觉还可以,看了一些基础概念和主题,写了几个测试程序,突然想起来了前一段时间在W ...

  6. UWP学习目录整理

    UWP学习目录整理 0x00 可以忽略的废话 10月6号靠着半听半猜和文字直播的补充看完了微软的秋季新品发布会,信仰充值成功,对UWP的开发十分感兴趣,打算后面找时间学习一下.谁想到学习的欲望越来越强 ...

  7. UWP开发必备:常用数据列表控件汇总比较

    今天是想通过实例将UWP开发常用的数据列表做汇总比较,作为以后项目开发参考.UWP开发必备知识点总结请参照[UWP开发必备以及常用知识点总结]. 本次主要讨论以下控件: GridView:用于显示数据 ...

  8. UWP开发必备以及常用知识点总结

    一直在学UWP,一直在写Code,自己到达了什么水平?还有多少东西需要学习才能独挡一面?我想对刚接触UWP的开发者都有这种困惑,偶尔停下来总结分析一下还是很有收获的! 以下内容是自己开发中经常遇到的一 ...

  9. UWP开发之Mvvmlight实践九:基于MVVM的项目架构分享

    在前几章介绍了不少MVVM以及Mvvmlight实例,那实际企业开发中将以那种架构开发比较好?怎样分层开发才能节省成本? 本文特别分享实际企业项目开发中使用过的项目架构,欢迎参照使用!有不好的地方欢迎 ...

随机推荐

  1. Python3实战系列之三(获取印度售后数据项目)

    问题:续接上一篇.说干咱就干呀,勤勤恳恳写程序呀! 目标:实现第一个python程序的“Hello world!” 解决方案:新建一个项目Test,创建一个Test.py文件.在文件中实现打印出“He ...

  2. python+selenium环境配置及浏览器调用

    最近在学习python自动化,从项目角度和技术基础角度出发,我选择了python+selenium+appium的模式开始我的自动化测试之旅: 一.python安装 二.python IDE使用简介 ...

  3. java中HashMap的基本方法使用

    遍历,添加词,等等 package test; import java.util.HashMap; import java.util.Iterator; import java.util.ArrayL ...

  4. 软件工程网络15个人作业4--Alpha阶段个人总结

    一.个人总结 在alpha 结束之后, 每位同学写一篇个人博客, 总结自己的alpha 过程: 请用自我评价表:http://www.cnblogs.com/xinz/p/3852177.html 有 ...

  5. 数据分析处理库pandas及可视化库Matplotlib

    一.读取文件 1)读取文件内容 import pandas info = pandas.read_csv('1.csv',encoding='gbk') # 获取文件信息 print(info) pr ...

  6. python学习 day15 (3月20日)----time

    # '2019-03-20 10:40:00'#这个时间向后推一个月 f1 = time.strptime('2019-03-20 10:40','%Y-%m-%d %H:%M') # 把字符串时间转 ...

  7. Codeforces gym 102062 简要题解

    文章目录 A. Bob and BoB B. Vibranium Gift C. The Blood Moon D. Palindrome and Chocolate E. Jumpy Robot F ...

  8. 2018.12.15 bzoj3676: [Apio2014]回文串(后缀自动机)

    传送门 对原串建立一个后缀自动机,然后用反串在上面匹配. 如果当前匹配的区间[l,r][l,r][l,r]包裹了当前状态的endposendposendpos中的最大值,那么[l,maxpos][l, ...

  9. maven 中央仓库地址 随笔记下了

    Maven 中央仓库地址: 1. http://www.sonatype.org/nexus/ 2. http://mvnrepository.com/ 3. http://repo1.maven.o ...

  10. latex字体

    强调 方式:声明:\em 或者 命令\emph,后者是latex2e的命令 区别:声明与命令的作用范围不同:\em改变当前字体直到被其他相应的声明取消(也可以是\em本身),或者当前的环境结束为止,当 ...