如何将GridViewEX升级到UWP(Universal Windows Platform)平台
引言
上一篇文章中,我们主要讲解了如何在保证gridview控件的用户体验基础上,扩展gridview生成gridviewex控件,增加动态添加新分组功能等,本文在上文的基础上,介绍如何在windows10中使用gridviewex,开发uwp应用。
demo 下载:
gridviewlivetiles.zip
gridviewex.zip
gridviewdemo.zip
开发uwp应用程序
开发uwp应用程序最好是从创建empty项目开始,重用已开发的一些模块,这样可以提高开发效率。
本文为了创建uwp 应用程序,首先创建一些通用类如下,详细代码见附件:
- common/visibilityconverter.cs
- common/layoutawarepage.cs
- common/suspensionmanager.cs
datamodel 和sample 文件夹下的所有文件都可以重用。
修改布局和导航
visibilityconverter 和 suspensionsmanager暂时不需要修改,可直接在uwp中使用。主要修改布局和导航逻辑文件。
由于微软支持的设备种类越来越多,导致applicationviewstate不再适用。uwp平台提供了其他的解决方法如adaptivetriggers,内置了自适应布局。因此创建uwp应用程序,首先需要删除所有
applicationviewstates的代码。可能会导致使用
报错。因此我们需要做一些兼容性的改变。layoutawarepage的部分会
无论是winrt还是uwp应用,都会使用返回键导航。桌面winrtx应用会在xaml文件添加返回按钮。但是在uwp应用中,非常灵活,桌面应用可以在标题栏中添加返回按钮,在移动设备中不仅能使用标题栏中的返回键,也可以使用物理返回键实现导航功能。uwp的方法比较通用,且不需要编写自定义的xaml文件。因此只需要开发一个基类,应用到不同的xaml 页面中就可以实现轻松实现导航功能,不需要重复编写代码。修改后的layoutawarepage 类:
1: protected override void onnavigatedto(navigationeventargs e)
2: {
3: // subscribe on back button event
4: if (iswindowsphonedevice())
5: {
6: // use hardware button
7: windows.phone.ui.input.hardwarebuttons.backpressed += hardwarebuttons_backpressed;
8: }
9: else
10: {
11: // enable/disable window back button depending on navigation state
12: var currentview = systemnavigationmanager.getforcurrentview();
13: currentview.appviewbackbuttonvisibility = this.frame != null && this.frame.cangoback ?
14: appviewbackbuttonvisibility.visible : appviewbackbuttonvisibility.collapsed;
15: currentview.backrequested += backbutton_tapped;
16: }
17: ...
18: protected override void onnavigatedfrom(navigationeventargs e)
19: {
20: // unsubscribe from back button event
21: if (iswindowsphonedevice())
22: {
23: windows.phone.ui.input.hardwarebuttons.backpressed -= hardwarebuttons_backpressed;
24: }
25: else
26: {
27: // unsubscribe from window back button
28: var currentview = systemnavigationmanager.getforcurrentview();
29: currentview.backrequested -= backbutton_tapped;
30: }
31: ...
32: // handle back button events
33: private void hardwarebuttons_backpressed(object sender, backpressedeventargs e)
34: {
35: if (this.frame != null && this.frame.cangoback)
36: {
37: e.handled = true;
38: this.frame.goback();
39: }
40: }
41: private void backbutton_tapped(object sender, backrequestedeventargs e)
42: {
43: this.goback(this, new routedeventargs());
44: }
因为需要使用物理返回键,我们需要在程序中添加引用文件“windows mobile extensions for the uwp”。
现在由layoutawarepage派生而来的所有页面都可直接使用,无需在多个文件中添加引用。
layoutawarepage 类最后添加设备查询的静态方法,来检测运行时设备。
1: public static bool iswindowsphonedevice()
2: {
3: if (windows.foundation.metadata.apiinformation.istypepresent(windows.phone.ui.input.hardwarebuttons))
4: {
5: return true;
6: }
7: return false;
8: }
其他平台
1. 如果想保证应用程序在windows10中具有与一致的界面风格和用户体验,可使用windows 10 themeresources (主题资源)。
2. 微软也在windows10 发布中升级了gridview控件,相对于windows 8 版本来说,最重要的改变是添加了用户重定向检测。
3. variablesizedwrapgrid 面板也添加了重定向检测功能。并且去掉了行和列自动展开的功能。下面是windows8 版本的xaml文件,在windows10 中已经无法使用。
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
最好的解决方法就是将variablesizedwrapgrid 与item的属性绑定,并将值传给自定义的gridview控件的listviewitempresenter 元素:
1: ///
2: /// this class sets variablesizedwrapgrid.columnspanproperty for gridviewitem controls,
3: /// so that every item can have different size in the variablesizedwrapgrid.
4: /// also it sets verticalcontentalignment and horizontalcontentalignment to stretch.
5: ///
6: public class gridviewtiled : gridview
7: {
8: // set columnspan according to the business logic (maybe some gridviewsamples.samples.item or group properties)
9: protected override void preparecontainerforitemoverride(windows.ui.xaml.dependencyobject element, object item)
10: {
11: element.setvalue(contentcontrol.horizontalcontentalignmentproperty, horizontalalignment.stretch);
12: element.setvalue(contentcontrol.verticalcontentalignmentproperty, verticalalignment.stretch);
13: uielement el = item as uielement;
14: if (el != null)
15: {
16: int colspan = windows.ui.xaml.controls.variablesizedwrapgrid.getcolumnspan(el);
17: int rowspan = windows.ui.xaml.controls.variablesizedwrapgrid.getrowspan(el);
18: if (rowspan > 1)
19: {
20: // only set it if it has non-defaul value
21: element.setvalue(windows.ui.xaml.controls.variablesizedwrapgrid.rowspanproperty, rowspan);
22: }
23: if (colspan > 1)
24: {
25: // only set it if it has non-defaul value
26: element.setvalue(windows.ui.xaml.controls.variablesizedwrapgrid.columnspanproperty, colspan);
27: }
28: }
29: base.preparecontainerforitemoverride(element, item);
30: }
31: }
uwp中的xaml文件:
新占位符(newgroupplaceholder)控件
winrt版的gridviewex控件使用了简单border作为新分组的占位符,在拖拽项过程中外观是静态的,无法改变。为了使界面对用户更加友好,并且将拖放的位置高亮, 因此我们新建了新的“
newgroupplaceholder
”控件,在拖拽过程中有简单的状态切换逻辑。代码很简单,见附件,系统提供的控件模板代码如下:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
修改gridviewex 控件
接下来,我们将介绍如何修改gridviewex控件,使得其可以适应uwp。
uwp平台下运行gridviewex大部分的功能与winrt保持一致。只有ondragover中的drageventargs.acceptedoperation 属性需要重写。显然uwp 中的gridview 将所有非空项的该属性都设置为none。因此,如果不重写ondragover 方法,drop 事件就不会被触发。
代码如下:
1: protected override void ondragover(drageventargs e)
2: {
3: int newindex = getdragoverindex(e);
4: if (newindex >= 0)
5: {
6: e.acceptedoperation = windows.applicationmodel.datatransfer.datapackageoperation.move;
运行代码时编译器会发出很多关于itemcontainergenerator 方法的警告,调用itemscontrol 响应方法就可以处理warning
variablesizedwrapgrid存在很多限制,为了解决这些限制,在上述代码中添加 preparecontainerforitemoverride 方法。最后需要升级gridviewex 控件自带的样式,使其支持设备重定向。
更加适应手持设备
在gridviewex控件中添加新的
preparingcontainerforitem 事件,该事件的参数即包含数据对象,也包含ui 容器,因此可根据需求设置ui属性,代码如下:
1: ///
2: /// set column spans depending on group id.
3: ///
4: ///
5: ///
6: private void gve_preparingcontainerforitem(object sender, gridviewex.preparingcontainerforitemeventargs e)
7: {
8: try
9: {
10: item it = e.item as item;
11: if (it != null)
12: {
13: e.element.setvalue(windows.ui.xaml.controls.variablesizedwrapgrid.columnspanproperty, it.groupid % 2 + 1);
14: }
15: }
16: catch
17: {
18: e.element.setvalue(windows.ui.xaml.controls.variablesizedwrapgrid.columnspanproperty, 1);
19: }
20: }
在多设备中具有良好用户体验
为了适应多种设备,需要生成自适应布局。本文中主要通过修改内容项的尺寸来实现该功能。创建了bound ,unbound以及grouped 示例文件,grouped 显示单个gridview控件,因此在移动端能够修改tile的尺寸及边框。
bound 和unbound 示例是由2个gridview控件组成,小屏幕中显的内容较多,无法显示更多的细节性的内容,因此使用pivot控件保证同一时间只显示一个gridview控件,并支持gridview之间切换。
代码如下:
1: public double tilesize
2: {
3: get { return (double)getvalue(tilesizeproperty); }
4: set { setvalue(tilesizeproperty, value); }
5: }
6: public static readonly dependencyproperty tilesizeproperty =
7: dependencyproperty.register(nameof(tilesize), typeof(double), typeof(customized), new propertymetadata(100));
8: public customized()
9: {
10: if (iswindowsphonedevice())
11: {
12: tilesize = 72;
13: }
14: this.initializecomponent();
15: }
gridviewex 和gridview 中绑定代码如下:
1:
2:
3:
4: itemwidth={binding tilesize, elementname=pageroot}
5: orientation=horizontal maximumrowsorcolumns=10/>
6:
7:
总结
自定义gridviewex控件扩展了gridview控件,丰富了功能,并新增适应uwp平台app的开发。
示例图片:
上一篇: 39个大数据可视化工具安利
下一篇: SQLServer之数据类型解析