如何将GridViewEX升级到UWP(Universal Windows Platform)平台
引言
上一篇文章中,我们主要讲解了如何在保证GridView控件的用户体验基础上,扩展GridView生成GridViewEx控件,增加动态添加新分组功能等,本文在上文的基础上,介绍如何在Windows10中使用GridViewEx,开发UWP应用。
Demo 下载:
开发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: <GridView Grid.Row="1" Grid.Column="1" Margin="10" AllowDrop="True" CanReorderItems="True" CanDragItems="True" IsSwipeEnabled="True">
- 2: <GridView.ItemsPanel>
- 3: <ItemsPanelTemplate>
- 4: <VariableSizedWrapGrid/>
- 5: </ItemsPanelTemplate>
- 6: </GridView.ItemsPanel>
- 7: <Rectangle Height="100" Width="200" Fill="Blue" />
- 8: <Rectangle Height="100" Width="100" Fill="Red" />
- 9: <Rectangle Height="100" Width="100" Fill="Yellow" />
- 10: <Rectangle Height="100" Width="100" Fill="Green" />
最好的解决方法就是将VariableSizedWrapGrid 与item的属性绑定,并将值传给自定义的GridView控件的ListViewItemPresenter 元素:
- 1: /// <summary>
- 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: /// </summary>
- 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文件:
- <controls:GridViewTiled Grid.Row="1" Grid.Column="1" Margin="10" AllowDrop="True" CanReorderItems="True" CanDragItems="True" >
- <controls:GridViewTiled.ItemsPanel>
- <ItemsPanelTemplate>
- <VariableSizedWrapGrid ItemHeight="100" ItemWidth="100" Orientation="Horizontal"/>
- </ItemsPanelTemplate>
- </controls:GridViewTiled.ItemsPanel>
- <Rectangle VariableSizedWrapGrid.ColumnSpan="2" VariableSizedWrapGrid.RowSpan="2" Fill="Blue" />
- <Rectangle Fill="Red" />
- <Rectangle Fill="Yellow" />
- <Rectangle Fill="Green" />
新占位符(NewGroupPlaceholder)控件
WinRT版的GridViewEx控件使用了简单border作为新分组的占位符,在拖拽项过程中外观是静态的,无法改变。为了使界面对用户更加友好,并且将拖放的位置高亮, 因此我们新建了新的“NewGroupPlaceholder
”控件,在拖拽过程中有简单的状态切换逻辑。
代码很简单,见附件,系统提供的控件模板代码如下:
- 1: <Style TargetType="local:NewGroupPlaceholder">
- 2: <Setter Property="Background" Value="Transparent" />
- 3: <Setter Property="Margin" Value="8" />
- 4: <Setter Property="Height" Value="32" />
- 5: <Setter Property="Template">
- 6: <Setter.Value>
- 7: <ControlTemplate TargetType="local:NewGroupPlaceholder">
- 8: <Border x:Name="root" Background="{TemplateBinding Background}">
- 9: <VisualStateManager.VisualStateGroups>
- 10: <VisualStateGroup x:Name="DragStates">
- 11: <VisualState x:Name="Normal"/>
- 12: <VisualState x:Name="DragOver">
- 13: <Storyboard>
- 14: <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="dragOverElement"/>
- 15: </Storyboard>
- 16: </VisualState>
- 17: </VisualStateGroup>
- 18: </VisualStateManager.VisualStateGroups>
- 19: <Border x:Name="dragOverElement" Background="{ThemeResource SystemControlHighlightListAccentLowBrush}" Opacity="0"/>
- 20: </Border>
- 21: </ControlTemplate>
- 22: </Setter.Value>
- 23: </Setter>
- 24: </Style>
修改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: /// <summary>
- 2: /// Set column spans depending on group id.
- 3: /// </summary>
- 4: /// <param name="sender"></param>
- 5: /// <param name="e"></param>
- 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: <GroupStyle.Panel>
- 2: <ItemsPanelTemplate>
- 3: <VariableSizedWrapGrid ItemHeight="{Binding TileSize, ElementName=pageRoot}"
- 4: ItemWidth="{Binding TileSize, ElementName=pageRoot}"
- 5: Orientation="Horizontal" MaximumRowsOrColumns="10"/>
- 6: </ItemsPanelTemplate>
- 7: </GroupStyle.Panel>
总结
自定义GridViewEx控件扩展了GridView控件,丰富了功能,并新增适应UWP平台App的开发。
示例图片:
UWP平台开发工具
ComponentOne Studio for UWP,是一套可以编写所有 UWP 平台应用的控件集,包括表格、报表、图表、仪表盘、组织图、地图、PDF、Excel、Word、日程安排、输入、导航等多个控件,有效帮助开发过程。
原文链接:http://www.codeproject.com/Articles/1037059/How-to-Upgrade-Extended-GridView-from-WinRT-to-Uni
如何将GridViewEX升级到UWP(Universal Windows Platform)平台的更多相关文章
- DEPLOYING NATIVE UWP (UNIVERSAL WINDOWS PLATFORM) APPS FOR JAVA DEVELOPERS & PUBLISHING THEM TO THE MICROSOFT STORE
原文: DEPLOYING NATIVE UWP (UNIVERSAL WINDOWS PLATFORM) APPS FOR JAVA DEVELOPERS & PUBLISHING THEM ...
- 操作系统-Windows:UWP(Universal Windows Platform)
ylbtech-操作系统-Windows:UWP(Universal Windows Platform) 1.返回顶部 1. UWP即Windows 10中的Universal Windows Pla ...
- 将Win8.1/WP8.1应用迁移到Universal Windows Platform
在上一篇在VS2015 RC打开CTP中创建的工程,我们介绍了怎么在RC中打开CTP中创建的Universal 工程,这一篇我们来讲下怎么将Windows 8.1/WP8.1的应用迁移到Univers ...
- Win10 Migrate apps to the Universal Windows Platform (UWP)
https://msdn.microsoft.com/en-us/library/mt148501.aspx
- 使用 .NET 平台,如何玩转 Universal Windows 应用?
2015年7月30日 本文作者是 Managed Languages 团队项目经理 Lucian Wischik. 不久前,Visual Studio 2015上新增 Windows 10 应用的开发 ...
- 如何使用 App Studio 快速定制你自己的 Universal Windows App
之前我为大家介绍过 App Studio 这只神器可以帮助大家快速制作一个 Windows Phone 8 的应用,今天之所以在写一篇关于 App Studio 的文章是因为,App Studio 经 ...
- 怎样使用 App Studio 高速定制你自己的 Universal Windows App
今天之所以在写一篇关于 App Studio 的文章是由于,App Studio 经过了几次升级功能得到了明显提升还能够调用系统功能了.而且能够更方便的和应用商店关联公布 Universal Wind ...
- 详解 UWP (通用 Windows 平台) 中的两种 HttpClient API
UWP (通用 Windows 平台) 应用开发者在构建通过 HTTP 与 Web 服务或服务器断点交互的应用时,有多种 API 可以选择.要在一个托管 UWP 应用中实现 HTTP 客户端角色,最常 ...
- Windows 下的高 DPI 应用开发(UWP / WPF / Windows Forms / Win32)
本文将介绍 Windows 系统中高 DPI 开发的基础知识.由于涉及到坐标转换,这种转换经常发生在计算的不知不觉中:所以无论你使用哪种 Windows 下的 UI 框架进行开发,你都需要了解这些内容 ...
随机推荐
- 结合阿里云服务器,设置家中jetson tk1随时远程登陆
前提条件: 1.路由配置dmz主机为tk1的ip ,设置路由器中ssh 端口22的访问权限 2.有一台远程服务器,服务器安装了php可以运行php文件(我使用的是阿里云) 家中tk1配置: 脚本pyt ...
- 原子操作--ARM架构
说明:内核版本号为3.10.101 一.ARM架构中的原子操作实现 在原子操作(一)中我们已经提到,各个架构组织为“复仇者”联盟,统一了基本的原子变量操作,这里我们就拿atomic_dec(v)来看看 ...
- window下flask开发环境搭建
1.安装python 官网下载https://www.python.org/downloads/,按提示安装就行,记住安装目录,把它添加到系统path中. 2.安装pip 官网下载pip文件:http ...
- 题目:利用条件运算符的嵌套来完成此题:学习成绩>=90分的同学用A表示,60-89分之间的用B表示,60分以下的用C表示。
public class Five_05 { public static void main(String[] args) { Scanner input=new Scanner(System.in) ...
- Web调试利器OpenWindow
有些时候调试web页面,在循环里面我们不方便设置断点进行调试,或者调试起来比较麻烦,我们就可以用openWindow的方法打印出想要查看的信息,既方便又省时. 代码如下: OpenWindow = w ...
- Bootstrap 折叠(Collapse)插件
折叠(Collapse)插件可以很容易地让页面区域折叠起来.无论您用它来创建折叠导航还是内容面板,它都允许很多内容选项. 如果您想要单独引用该插件的功能,那么您需要引用 collapse.js.同时, ...
- IT小喇叭-企业品牌宣传、产品营销推广的首选
IT小喇叭-企业品牌宣传.产品营销推广的首选 IT小喇叭,成立于2015年6月初,成都芮嘉科技有限公司旗下产品,主要进行媒体资源整合.宣传报道:使移动互联网等相关企业的产品宣传.品牌营销变得更加方便. ...
- Spring学习笔记 6. 尚硅谷_佟刚_Spring_Bean 之间的关系
1,继承关系 首先从简单的代码来看,有一个Address类,配置文件有两个bean (1)Address类 package com.zsq; public class Address { privat ...
- 在 Mac OS 上使用 TypeScript 编写 ASP.NET Core 1.0 应用
var appInsights=window.appInsights||function(config){ function r(config){t[config]=function(){var i= ...
- JSF中使用jquery拦截ajax请求
jsf提供一个内置的jsf.ajax.request方法给我们使用,如果在jquery中使用,则需要做一些更改. 此处因为使用jquery,所以可以不必在控件中添加onclick方法了,可以给控件配 ...