最近有童鞋有这种需求,说实话我不知道这个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. 移动端300ms延迟由来及解决方案

    1.300ms延迟由来 300 毫秒延迟的主要原因是解决双击缩放(double tap to zoom).双击缩放,顾名思义,即用手指在屏幕上快速点击两次,iOS 自带的 Safari 浏览器会将网页 ...

  2. fastcgi协议解析(nginx)

    请求NGINX ->[ {(post data) +> (NGX_HTTP_FASTCGI_STDIN)} * N +> {(environment variables) +> ...

  3. 通过flask中的Response返回json数据

    使用flask的过程中,发现有时需要生成一个Response并返回.网上查了查,看了看源码,找到了两种办法: from flask import Response, json Response(jso ...

  4. 64位ubuntu 兼容32位

    http://www.cnblogs.com/mliudong/p/4086797.html 首先要打开64位系统对32位的支持 第一步:确认64为架构的内核 dpkg --print-archite ...

  5. centos上安装jdk

    今天在centos上安装jdk,总结步骤如下:1.先到oracle下载rpm包:jdk-7u80-linux-x64.rpm (下载地址在百度找找)2.把jdk-7u80-linux-x64.rpm上 ...

  6. linux中命令突然不能用

    先用:echo $PATH 发现path丢失:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin 于是用临时环境变量 export ...

  7. 用百度AI的OCR文字识别结合JAVA实现了图片的文字识别功能

    第一步可定要获取百度的三个东西 要到百度AI网站(http://ai.baidu.com/)去注册 然后获得 -const APP_ID = '请填写你的appid'; -const API_KEY ...

  8. 2018.11.06 洛谷P1941 飞扬的小鸟(背包)

    传送门 上升看成完全背包. 下降看成01背包. 注意边界转移就行了. 代码: #include<bits/stdc++.h> using namespace std; inline int ...

  9. latex字体

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

  10. Javascript、Jquery获取浏览器和屏幕各种高度宽度(单位都为px)

    Javascript.Jquery获取浏览器和屏幕各种高度宽度 另外参见    http://www.cnblogs.com/top5/archive/2009/05/07/1452135.html ...