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实例,那实际企业开发中将以那种架构开发比较好?怎样分层开发才能节省成本? 本文特别分享实际企业项目开发中使用过的项目架构,欢迎参照使用!有不好的地方欢迎 ...
随机推荐
- android windows的一些item属性
<item name="android:windowFrame">@null</item> :Dialog的windowFrame框为无 <item ...
- 提升HTML5的性能体验系列之一 避免切页白屏
窗体切换白屏的现实问题 HTML5的性能比原生差很多,比如切页时白屏.列表滚动不流畅.下拉刷新和上拉翻页卡顿.在低端Android手机上,很多原生App常用的功能和体验效果都很难使用HTML5技术模拟 ...
- 基于Web Service的客户端框架搭建一:C#使用Http Post方式传递Json数据字符串调用Web Service
引言 前段时间一直在做一个ERP系统,随着系统功能的完善,客户端(CS模式)变得越来越臃肿.现在想将业务逻辑层以下部分和界面层分离,使用Web Service来做.由于C#中通过直接添加引用的方来调用 ...
- make/makefile中的加号+,减号-和at号@的含义
http://www.crifan.com/order_make__makefile_in_the_plus__minus_-_and_at_the_meaning_of_numbers/ 在看mak ...
- SQL SERVER 如果判断text类型数据不为空
一个字段Remark的数据类型设置先设置为varcharr(255),后来考虑到扩展性需要将其定义为TEXT类型,但是SQL 语句报错. SQL 语句: SELECT * FROM ...
- iOS知识基础篇 static
static关键字的作用 一.隐藏 通过static修饰的函数或者变量,在该文件中,所有位于这条语句之后的函数都可以访问,而其他文件中的方法和函数则不行: 二.静态变量 类方法不可以访问实例变量(函 ...
- 2018.11.06 bzoj1040: [ZJOI2008]骑士(树形dp)
传送门 由题可知给出的是基环森林. 因此对于每个基环森林找到环断开dpdpdp两次就行了. 代码: #include<bits/stdc++.h> using namespace std; ...
- 枚举子窗口EnumChildWindows()的应用
1.EnumChildWindows()函数的作用枚举子窗口(按顺序调用回调函数,并将子窗口的句柄传递给了回调函数).函数原型: BOOL WINAPI EnumChildWindows( HWND ...
- 关于xftp上传文件状态错误的解决
新建一个文件夹,/usr/local/wwj 更改wwj权限 chmod 777 wwj 然后就可以上传了 如果还不行,就关闭防火墙
- CodeForces 946D Timetable (DP)
题意:给定 n,m,K,表示某个人一个周有 n 天,每天有 m 节课,但是他可以跳过 K 节课,然后下面每行一个长度为 m 个01字符串,0 表示该人在这一小时没有课,1 表示该人在这一个小时有课,每 ...