UWP开发入门(十)——通过继承来扩展ListView
本篇之所以起这样一个名字,是因为重点并非如何自定义控件,不涉及创建CustomControl和UserControl使用的Template和XAML概念。而是通过继承的方法来扩展一个现有的类,在继承的子类中增加属性和扩展行为。
我们在《UWP开发入门(七)——下拉刷新》中提到过嵌套ScrollViewer的实现思路,本篇我们对ListView的第一个扩展行为,即是摒弃嵌套的做法,而是通过访问ListView内部的ScrollViewer控件,来监听ViewChanged事件。
访问ListView内部的ScrollViewer,必定离不开VisualTreeHelper类中的以下两个方法:
public static DependencyObject GetChild(DependencyObject reference, System.Int32 childIndex); public static System.Int32 GetChildrenCount(DependencyObject reference);
可以将这两个方法进一步组合得到:
static T FindFirstChild<T>(FrameworkElement element) where T : FrameworkElement
{
int childrenCount = VisualTreeHelper.GetChildrenCount(element);
var children = new FrameworkElement[childrenCount]; for (int i = ; i < childrenCount; i++)
{
var child = VisualTreeHelper.GetChild(element, i) as FrameworkElement;
children[i] = child;
if (child is T)
return (T)child;
} for (int i = ; i < childrenCount; i++)
if (children[i] != null)
{
var subChild = FindFirstChild<T>(children[i]);
if (subChild != null)
return subChild;
} return null;
}
该方法通过递归来遍历FrameworkElement内部的元素,并返回第一个符合类型的元素。ListViewEx的第一个扩展如下:
public class ListViewEx : ListView, INotifyPropertyChanged
{
private ScrollViewer _scrollViewer; public event EventHandler LoadHistoryEvent;
public event PropertyChangedEventHandler PropertyChanged; protected void OnProperyChanged([CallerMemberName] string name = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
} public ListViewEx()
{
this.Loaded += ListViewEx_Loaded;
this.Unloaded += ListViewEx_Unloaded;
} private void ListViewEx_Unloaded(object sender, RoutedEventArgs e)
{
this.Unloaded -= ListViewEx_Unloaded;
if (_scrollViewer != null)
{
_scrollViewer.ViewChanged -= Sv_ViewChanged;
}
} private void ListViewEx_Loaded(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
this.Loaded -= ListViewEx_Loaded;
_scrollViewer = FindFirstChild<ScrollViewer>(this);
if (_scrollViewer != null)
{
_scrollViewer.ViewChanged += Sv_ViewChanged;
}
} private async void Sv_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
{
if (e.IsIntermediate == false && _scrollViewer.VerticalOffset < )
{
_scrollViewer.ChangeView(null, , null);
await Task.Delay();
LoadHistoryEvent?.Invoke(this, EventArgs.Empty);
}
}
嗯嗯,可以看到优雅的 -= event和恰到好处的null check,啊啊!忍不住想点个赞!在ViewChanged事件监测到滚动条到达顶部后,果断触发ListViewEx内定义的LoadHistoryEvent来通知更新数据。
本篇如果仅增加一个LoadHistoryEvent,又会被人非议是在补完前篇,一篇拆成两篇写……那好吧,我们再给ListViewEx增加第二个扩展GoBottomVisiblity属性,顾名思义即是ListViewEx向上滚动几屏以后,显示一个GoBottom的按钮。
在ListViewEx的类中,首先定义属性GoBottomVisibility,然后同样是在ViewChanged事件中,计算是否显示GoBottom按钮。
public Visibility GoBottomVisiblity
{
get { return _goBottomVisiblity; }
set
{
_goBottomVisiblity = value;
this.OnProperyChanged();
}
}
private void Sv_ViewChanged2(object sender, ScrollViewerViewChangedEventArgs e)
{
if (e.IsIntermediate == false)
{
CheckGoBottomVisibility();
}
} private void CheckGoBottomVisibility()
{
if (_scrollViewer.VerticalOffset + _scrollViewer.ViewportHeight < _scrollViewer.ScrollableHeight)
{
GoBottomVisiblity = Visibility.Visible;
}
else
{
GoBottomVisiblity = Visibility.Collapsed;
}
}
代码没法全部贴上来,一个是太长了显得啰嗦,二是会被管理员说没内涵从首页删掉……
大体上本篇就是给ListView扩展了LoadHistoryEvent事件和GoBottomVisibility属性。最后说说怎么用,XAML里使用ListViewEx代替默认的ListView,会发现多出一个LoadHistoryEvent,挂上加载数据的事件就OK了。然后在列表的下部画一个三角箭头,Visibility绑定到ListViewEx的GoBottomVisibility属性上就收工了。

<Grid>
<local:ListViewEx x:Name="listViewEx" ItemsSource="{x:Bind Items}" LoadHistoryEvent="ListViewEx_LoadHistoryEvent"></local:ListViewEx>
<Grid Margin="10" VerticalAlignment="Bottom" HorizontalAlignment="Center"
Tapped="Grid_Tapped" Visibility="{x:Bind listViewEx.GoBottomVisiblity,Mode=OneWay}">
<Ellipse Fill="LightGray" Width="30" Height="30"></Ellipse>
<Polyline Stroke="White" Points="10,10 15,20 20,10"></Polyline>
</Grid>
</Grid>
完整代码放在GayHub上,地址:https://github.com/manupstairs/UWPSamples
非常感谢各位捧场,能够点开页面看到这里,拜谢了!Orz
UWP开发入门(十)——通过继承来扩展ListView的更多相关文章
- UWP开发入门(十六)——常见的内存泄漏的原因
本篇借鉴了同事翔哥的劳动成果,在巨人的肩膀上把稿子又念了一遍. 内存泄漏的概念我这里就不说了,之前<UWP开发入门(十三)——用Diagnostic Tool检查内存泄漏>中提到过,即使有 ...
- UWP开发入门(四)——自定义CommandBar
各位好,再次回到UWP开发入门系列,刚回归可能有些不适应,所以今天我们讲个简单的,自定义CommandBar,说通俗点就是自定义类似AppBarButton的东西,然后扔到CommandBar中使用. ...
- UWP开发入门系列笔记之(一):UWP初览
标签: 随着微软Build2015带来的好消息,Win10正式版发布的日子已经离我们越来越近了,我们也终于欣喜地看到:一个统一的Windows平台对于开发人员来说充满了吸引力,这局棋下的好大的说--于 ...
- UWP开发入门(25)——通过Radio控制Bluetooth, WiFi
回顾写了许久的UWP开发入门,竟然没有讲过通过Windows.Devices.Radios.Radio来控制Bluetooth和WiFi等功能的开关.也许是因为相关的API设计的简单好用,以至于被我给 ...
- UWP开发入门(十一)——Attached Property的简单应用
UWP中的Attached Property即附加属性,在实际开发中是很常见的,比如Grid.Row: <Grid Background="{ThemeResource Applica ...
- UWP开发入门(七)——下拉刷新
本篇意在给这几天Win10 Mobile负面新闻不断的某软洗地,想要证明实现一个简单的下拉刷新并不困难.UWP开发更大的困难在于懒惰,缺乏学习的意愿.而不是“某软连下拉刷新控件都没有”这样的想法. 之 ...
- UWP开发入门(一)——SplitView
接下来会写一个UWP(Universal Windows Platform)开发入门的系列,自己学习到哪里,有什么心得总结,就会写到哪里.本篇对适用于顶层导航的SplitView控件展开讨论. 首先S ...
- UWP开发入门(二十三)——WebView
本篇讨论在UWP开发中使用WebView控件时常见的问题,以及一些小技巧. WebView是实际开发中常用的控件,很多大家抱怨的套网页的应用都是通过WebView来实现的.这里要澄清一个问题,套网页的 ...
- UWP开发入门(二十一)——保持Ui线程处于响应状态
GUI的程序有时候会因为等待一个耗时操作完成,导致界面卡死.本篇我们就UWP开发中可能遇到的情况,来讨论如何优化处理. 假设当前存在点击按钮跳转页面的操作,通过按钮打开的新页面,在初始化过程中存在一些 ...
随机推荐
- django2.0设置默认访问路由
搭建完毕后,打开域名,直接来个报错,如果没有访问的地址,是不合适的 在urls.py中定义,默认访问的路由 from django.contrib import admin from django.u ...
- php在线编辑本地文件方法共享
public function testfile() { $cfile='F:\phpStudy\WWW\thinkphp5practise\NNWinLoseConfig.ini'; $cfileh ...
- [Z] Windbg以及vs debug使用
Windbg 一篇中国人写的质量非常高的Windbg文章:篇中国人写的质量非常高的Windbg文章: http://www.yiiyee.cn/Blog/windbg/ code project上的W ...
- PowerDesigner 生成的脚本取掉双引号
建模工具PowerDesigner http://www.cnblogs.com/mcgrady/archive/2013/05/25/3098588.html 默认导出在带双引号,表名称后期使用的时 ...
- [AlgorithmStaff] Bresenham快速直线算法
操作系统:Windows8.1 显卡:Nivida GTX965M 开发工具:Unity2017.3 | NativeC 最近在学习 Unity tilemap Brush 自定义笔刷功能时候,看到其 ...
- windchill 跑物料变更流程后无法发送物料到SAP
2042000065.2042000064.2042000074.2042000066在发主数据时,流程卡住,SAP返回信息为空 核查:PLM后台日志只显示变更零件,开始,然后就结束 原因:ECR号为 ...
- eclipse-jee-mars-2-win32-x86_64安装activiti
离线安装老是不行,只能在线安装了 选择Activiti BPMN Desisner,然后一直选择下一步,直到出现如下窗体: 幸亏这个插件很小,在线安装也不算慢
- 「这样玩Hexo」修改主题自定义实现界面和功能的自定义
首发于个人博客 想获得更好的阅读体验,烦请移步⬆️ 前言 作为一个颜党,在换了许多Hexo的主题后,选择了现在使用的fexo主题.但是相比于大多数博主使用的NEXT,fexo还是不够powerful, ...
- leetcode 7 reverse integer 反转整数
描述: 给定32位整数,反转,如321转成123. 解决: 关键是溢出检测: int reverse(int x) { ; int temp; while (x) { temp = ret * + x ...
- juniper交换机配置
1.链接串口配置: minicom -s ```bash Serial port setup A - Serial Device : /dev/ttyS1 ...