UWP FillRowViewPanel
最近有童鞋有这种需求,说实话我不知道这个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的更多相关文章
- UWP 律师查询 MVVM
APP简介 律师查询是基于聚合数据的律师查询接口做的,这个接口目前处于停用状态,但是,由于我是之前申请的,所以,还可以用,应该是无法再申请了. 效果图 开发 一.HttpHelper 既然是请求接口的 ...
- 领域驱动和MVVM应用于UWP开发的一些思考
领域驱动和MVVM应用于UWP开发的一些思考 0x00 起因 有段时间没写博客了,其实最近本来是根据梳理的MSDN上的资料(UWP开发目录整理)有条不紊的进行UWP学习的.学习中有了心得体会或遇到了问 ...
- UWP中实现自定义标题栏
UWP中实现自定义标题栏 0x00 起因 在UWP开发中,有时候我们希望实现自定义标题栏,例如在标题栏中加入搜索框.按钮之类的控件.搜了下资料居然在一个日文网站找到了一篇介绍这个主题的文章: http ...
- UWP中新加的数据绑定方式x:Bind分析总结
UWP中新加的数据绑定方式x:Bind分析总结 0x00 UWP中的x:Bind 由之前有过WPF开发经验,所以在学习UWP的时候直接省略了XAML.数据绑定等几个看着十分眼熟的主题.学习过程中倒是也 ...
- MVVM框架从WPF移植到UWP遇到的问题和解决方法
MVVM框架从WPF移植到UWP遇到的问题和解决方法 0x00 起因 这几天开始学习UWP了,之前有WPF经验,所以总体感觉还可以,看了一些基础概念和主题,写了几个测试程序,突然想起来了前一段时间在W ...
- UWP学习目录整理
UWP学习目录整理 0x00 可以忽略的废话 10月6号靠着半听半猜和文字直播的补充看完了微软的秋季新品发布会,信仰充值成功,对UWP的开发十分感兴趣,打算后面找时间学习一下.谁想到学习的欲望越来越强 ...
- UWP开发必备:常用数据列表控件汇总比较
今天是想通过实例将UWP开发常用的数据列表做汇总比较,作为以后项目开发参考.UWP开发必备知识点总结请参照[UWP开发必备以及常用知识点总结]. 本次主要讨论以下控件: GridView:用于显示数据 ...
- UWP开发必备以及常用知识点总结
一直在学UWP,一直在写Code,自己到达了什么水平?还有多少东西需要学习才能独挡一面?我想对刚接触UWP的开发者都有这种困惑,偶尔停下来总结分析一下还是很有收获的! 以下内容是自己开发中经常遇到的一 ...
- UWP开发之Mvvmlight实践九:基于MVVM的项目架构分享
在前几章介绍了不少MVVM以及Mvvmlight实例,那实际企业开发中将以那种架构开发比较好?怎样分层开发才能节省成本? 本文特别分享实际企业项目开发中使用过的项目架构,欢迎参照使用!有不好的地方欢迎 ...
随机推荐
- 算法题思路总结和leecode继续历程
2018-05-03 刷了牛客网的题目:总结思路(总的思路跟数学一样就是化简和转化) 具体启发点: 1.对数据进行预处理排序的思想:比如8皇后问题 2.对一个数组元素进行比较的操作,如果复杂,可以试试 ...
- IOS初级:UIwindow
AppDelegate.h @property (strong, nonatomic) UIWindow *window; AppDelegate.m - (BOOL)application:(UIA ...
- putty中查询乱码问题
我们在putty连接Linux时候,有时候查询会出现乱码问题...如下图 这个是因为putty中设置编码字符集的原因..将此换为utf8格式的即可解决 解决后查询如下:
- c#里如何实现讲一个字符串数组例如 “112,221”转化成两个字符串数组“112” “221” 中间以逗号隔开
比如是S [0]="123,223" S[1]="111,222" ....... 想转化为 SX[0]="123" SX[1]=" ...
- 华为QOS原理及配置
http://www.tudou.com/programs/view/GWCiHfWC9FI/ FLASH : http://www.tudou.com/v/GWCiHfWC9FI/&reso ...
- centos6 搭建nginx实现负载均衡
一.安装nginx 1)准备2台服务器,环境一样,同时执行 rpm -ivh http://mirrors.aliyun.com/epel/epel-release-latest-6.noarch.r ...
- 模块and包
一.模块 1.import 加载的模块四个通用类别 1.使用python编写的py文件 2.已被编译为共享库或者DLL或者C\C++的扩展 3.包好一组模块的包 4.使用c编写并连接到python解释 ...
- 2018.11.17 hdu5829Rikka with Subset(ntt)
传送门 nttnttntt基础题. 考虑计算每一个数在排名为kkk时被统计了多少次来更新答案. 这样的话,设anskans_kansk表示所有数的值乘上排名为kkk的子集数的总和. 则ansk=∑i ...
- PC Access的使用
需要copy xxx.dll 到windows/syswow64 目录下 运行com注册 启动电脑后,自动锁定(在启动目录下架锁定程序) using System; using System.Col ...
- MPA(Macro Prudential Assessment)即宏观审慎评估体系
MPA(Macro Prudential Assessment)即宏观审慎评估体系.2015年12月29日,央行发布公告称,为进一步完善宏观审慎政策框架,更加有效地防范系统性风险,发挥逆周期调节作用, ...