引言

上一篇文章中,我们主要讲解了如何在保证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. 1: protected override void OnNavigatedTo(NavigationEventArgs e)
  1. 2: {
  1. 3: // subscribe on Back button event
  1. 4: if (IsWindowsPhoneDevice())
  1. 5: {
  1. 6: // use hardware button
  1. 7: Windows.Phone.UI.Input.HardwareButtons.BackPressed += HardwareButtons_BackPressed;
  1. 8: }
  1. 9: else
  1. 10: {
  1. 11: // enable/disable window back button depending on navigation state
  1. 12: var currentView = SystemNavigationManager.GetForCurrentView();
  1. 13: currentView.AppViewBackButtonVisibility = this.Frame != null && this.Frame.CanGoBack ?
  1. 14: AppViewBackButtonVisibility.Visible : AppViewBackButtonVisibility.Collapsed;
  1. 15: currentView.BackRequested += backButton_Tapped;
  1. 16: }
  1. 17: ...
  1. 18: protected override void OnNavigatedFrom(NavigationEventArgs e)
  1. 19: {
  1. 20: // unsubscribe from Back button event
  1. 21: if (IsWindowsPhoneDevice())
  1. 22: {
  1. 23: Windows.Phone.UI.Input.HardwareButtons.BackPressed -= HardwareButtons_BackPressed;
  1. 24: }
  1. 25: else
  1. 26: {
  1. 27: // unsubscribe from window back button
  1. 28: var currentView = SystemNavigationManager.GetForCurrentView();
  1. 29: currentView.BackRequested -= backButton_Tapped;
  1. 30: }
  1. 31: ...
  1. 32: // handle Back button events
  1. 33: private void HardwareButtons_BackPressed(object sender, BackPressedEventArgs e)
  1. 34: {
  1. 35: if (this.Frame != null && this.Frame.CanGoBack)
  1. 36: {
  1. 37: e.Handled = true;
  1. 38: this.Frame.GoBack();
  1. 39: }
  1. 40: }
  1. 41: private void backButton_Tapped(object sender, BackRequestedEventArgs e)
  1. 42: {
  1. 43: this.GoBack(this, new RoutedEventArgs());
  1. 44: }

因为需要使用物理返回键,我们需要在程序中添加引用文件“Windows Mobile Extensions for the UWP”。

现在由LayoutAwarePage派生而来的所有页面都可直接使用,无需在多个文件中添加引用。

LayoutAwarePage 类最后添加设备查询的静态方法,来检测运行时设备。

  1. 1: public static bool IsWindowsPhoneDevice()
  1. 2: {
  1. 3: if (Windows.Foundation.Metadata.ApiInformation.IsTypePresent("Windows.Phone.UI.Input.HardwareButtons"))
  1. 4: {
  1. 5: return true;
  1. 6: }
  1. 7: return false;
  1. 8: }

其他平台

1. 如果想保证应用程序在Windows10中具有与系统一致的界面风格和用户体验,可使用Windows 10 ThemeResources (主题资源)。

2. 微软也在Windows10 发布中升级了GridView控件,相对于Windows 8 版本来说,最重要的改变是添加了用户重定向检测。

3. VariableSizedWrapGrid 面板也添加了重定向检测功能。并且去掉了行和列自动展开的功能。下面是Windows8 版本的Xaml文件,在Windows10 中已经无法使用。

  1. 1: <GridView Grid.Row="1" Grid.Column="1" Margin="10" AllowDrop="True" CanReorderItems="True" CanDragItems="True" IsSwipeEnabled="True">
  1. 2: <GridView.ItemsPanel>
  1. 3: <ItemsPanelTemplate>
  1. 4: <VariableSizedWrapGrid/>
  1. 5: </ItemsPanelTemplate>
  1. 6: </GridView.ItemsPanel>
  1. 7: <Rectangle Height="100" Width="200" Fill="Blue" />
  1. 8: <Rectangle Height="100" Width="100" Fill="Red" />
  1. 9: <Rectangle Height="100" Width="100" Fill="Yellow" />
  1. 10: <Rectangle Height="100" Width="100" Fill="Green" />

最好的解决方法就是将VariableSizedWrapGrid 与item的属性绑定,并将值传给自定义的GridView控件的ListViewItemPresenter 元素:

  1. 1: /// <summary>
  1. 2: /// This class sets VariableSizedWrapGrid.ColumnSpanProperty for GridViewItem controls,
  1. 3: /// so that every item can have different size in the VariableSizedWrapGrid.
  1. 4: /// Also it sets VerticalContentAlignment and HorizontalContentAlignment to Stretch.
  1. 5: /// </summary>
  1. 6: public class GridViewTiled : GridView
  1. 7: {
  1. 8: // set ColumnSpan according to the business logic (maybe some GridViewSamples.Samples.Item or group properties)
  1. 9: protected override void PrepareContainerForItemOverride(Windows.UI.Xaml.DependencyObject element, object item)
  1. 10: {
  1. 11: element.SetValue(ContentControl.HorizontalContentAlignmentProperty, HorizontalAlignment.Stretch);
  1. 12: element.SetValue(ContentControl.VerticalContentAlignmentProperty, VerticalAlignment.Stretch);
  1. 13: UIElement el = item as UIElement;
  1. 14: if (el != null)
  1. 15: {
  1. 16: int colSpan = Windows.UI.Xaml.Controls.VariableSizedWrapGrid.GetColumnSpan(el);
  1. 17: int rowSpan = Windows.UI.Xaml.Controls.VariableSizedWrapGrid.GetRowSpan(el);
  1. 18: if (rowSpan > 1)
  1. 19: {
  1. 20: // only set it if it has non-defaul value
  1. 21: element.SetValue(Windows.UI.Xaml.Controls.VariableSizedWrapGrid.RowSpanProperty, rowSpan);
  1. 22: }
  1. 23: if (colSpan > 1)
  1. 24: {
  1. 25: // only set it if it has non-defaul value
  1. 26: element.SetValue(Windows.UI.Xaml.Controls.VariableSizedWrapGrid.ColumnSpanProperty, colSpan);
  1. 27: }
  1. 28: }
  1. 29: base.PrepareContainerForItemOverride(element, item);
  1. 30: }
  1. 31: }

UWP中的XAML文件:

  1. <controls:GridViewTiled Grid.Row="1" Grid.Column="1" Margin="10" AllowDrop="True" CanReorderItems="True" CanDragItems="True" >
  2. <controls:GridViewTiled.ItemsPanel>
  3. <ItemsPanelTemplate>
  4. <VariableSizedWrapGrid ItemHeight="100" ItemWidth="100" Orientation="Horizontal"/>
  5. </ItemsPanelTemplate>
  6. </controls:GridViewTiled.ItemsPanel>
  7. <Rectangle VariableSizedWrapGrid.ColumnSpan="2" VariableSizedWrapGrid.RowSpan="2" Fill="Blue" />
  8. <Rectangle Fill="Red" />
  9. <Rectangle Fill="Yellow" />
  10. <Rectangle Fill="Green" />

新占位符(NewGroupPlaceholder)控件

WinRT版的GridViewEx控件使用了简单border作为新分组的占位符,在拖拽项过程中外观是静态的,无法改变。为了使界面对用户更加友好,并且将拖放的位置高亮, 因此我们新建了新的“NewGroupPlaceholder”控件,在拖拽过程中有简单的状态切换逻辑。

代码很简单,见附件,系统提供的控件模板代码如下:

  1. 1: <Style TargetType="local:NewGroupPlaceholder">
  1. 2: <Setter Property="Background" Value="Transparent" />
  1. 3: <Setter Property="Margin" Value="8" />
  1. 4: <Setter Property="Height" Value="32" />
  1. 5: <Setter Property="Template">
  1. 6: <Setter.Value>
  1. 7: <ControlTemplate TargetType="local:NewGroupPlaceholder">
  1. 8: <Border x:Name="root" Background="{TemplateBinding Background}">
  1. 9: <VisualStateManager.VisualStateGroups>
  1. 10: <VisualStateGroup x:Name="DragStates">
  1. 11: <VisualState x:Name="Normal"/>
  1. 12: <VisualState x:Name="DragOver">
  1. 13: <Storyboard>
  1. 14: <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="dragOverElement"/>
  1. 15: </Storyboard>
  1. 16: </VisualState>
  1. 17: </VisualStateGroup>
  1. 18: </VisualStateManager.VisualStateGroups>
  1. 19: <Border x:Name="dragOverElement" Background="{ThemeResource SystemControlHighlightListAccentLowBrush}" Opacity="0"/>
  1. 20: </Border>
  1. 21: </ControlTemplate>
  1. 22: </Setter.Value>
  1. 23: </Setter>
  1. 24: </Style>

修改GridViewEx 控件

接下来,我们将介绍如何修改GridViewEx控件,使得其可以适应UWP。

UWP平台下运行GridViewEx大部分的功能与WinRT保持一致。只有OnDragOver中的DragEventArgs.AcceptedOperation 属性需要重写。显然UWP 中的GridView 将所有非空项的该属性都设置为None。因此,如果不重写OnDragOver 方法,Drop 事件就不会被触发。

代码如下:

  1. 1: protected override void OnDragOver(DragEventArgs e)
  1. 2: {
  1. 3: int newIndex = GetDragOverIndex(e);
  1. 4: if (newIndex >= 0)
  1. 5: {
  1. 6: e.AcceptedOperation = Windows.ApplicationModel.DataTransfer.DataPackageOperation.Move;

运行代码时编译器会发出很多关于ItemContainerGenerator 方法的警告,调用ItemsControl 响应方法就可以处理Warning

VariableSizedWrapGrid存在很多限制,为了解决这些限制,在上述代码中添加 PrepareContainerForItemOverride 方法。最后需要升级GridViewEx 控件自带的样式,使其支持设备重定向。

更加适应手持设备

在GridViewEx控件中添加新的PreparingContainerForItem 事件,该事件的参数即包含数据对象,也包含UI 容器,因此可根据需求设置UI属性,代码如下:

  1. 1: /// <summary>
  1. 2: /// Set column spans depending on group id.
  1. 3: /// </summary>
  1. 4: /// <param name="sender"></param>
  1. 5: /// <param name="e"></param>
  1. 6: private void gve_PreparingContainerForItem(object sender, GridViewEx.PreparingContainerForItemEventArgs e)
  1. 7: {
  1. 8: try
  1. 9: {
  1. 10: Item it = e.Item as Item;
  1. 11: if (it != null)
  1. 12: {
  1. 13: e.Element.SetValue(Windows.UI.Xaml.Controls.VariableSizedWrapGrid.ColumnSpanProperty, it.GroupId % 2 + 1);
  1. 14: }
  1. 15: }
  1. 16: catch
  1. 17: {
  1. 18: e.Element.SetValue(Windows.UI.Xaml.Controls.VariableSizedWrapGrid.ColumnSpanProperty, 1);
  1. 19: }
  1. 20: }

在多设备中具有良好用户体验

为了适应多种设备,需要生成自适应布局。本文中主要通过修改内容项的尺寸来实现该功能。创建了Bound ,Unbound以及Grouped 示例文件,Grouped 显示单个GridView控件,因此在移动端能够修改Tile的尺寸及边框。

Bound 和Unbound 示例是由2个GridView控件组成,小屏幕中显的内容较多,无法显示更多的细节性的内容,因此使用Pivot控件保证同一时间只显示一个GridView控件,并支持GridView之间切换。

代码如下:

  1. 1: public double TileSize
  1. 2: {
  1. 3: get { return (double)GetValue(TileSizeProperty); }
  1. 4: set { SetValue(TileSizeProperty, value); }
  1. 5: }
  1. 6: public static readonly DependencyProperty TileSizeProperty =
  1. 7: DependencyProperty.Register(nameof(TileSize), typeof(double), typeof(Customized), new PropertyMetadata(100));
  1. 8: public Customized()
  1. 9: {
  1. 10: if (IsWindowsPhoneDevice())
  1. 11: {
  1. 12: TileSize = 72;
  1. 13: }
  1. 14: this.InitializeComponent();
  1. 15: }

GridViewEx 和GridView 中绑定代码如下:

  1. 1: <GroupStyle.Panel>
  1. 2: <ItemsPanelTemplate>
  1. 3: <VariableSizedWrapGrid ItemHeight="{Binding TileSize, ElementName=pageRoot}"
  1. 4: ItemWidth="{Binding TileSize, ElementName=pageRoot}"
  1. 5: Orientation="Horizontal" MaximumRowsOrColumns="10"/>
  1. 6: </ItemsPanelTemplate>
  1. 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)平台的更多相关文章

  1. 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 ...

  2. 操作系统-Windows:UWP(Universal Windows Platform)

    ylbtech-操作系统-Windows:UWP(Universal Windows Platform) 1.返回顶部 1. UWP即Windows 10中的Universal Windows Pla ...

  3. 将Win8.1/WP8.1应用迁移到Universal Windows Platform

    在上一篇在VS2015 RC打开CTP中创建的工程,我们介绍了怎么在RC中打开CTP中创建的Universal 工程,这一篇我们来讲下怎么将Windows 8.1/WP8.1的应用迁移到Univers ...

  4. Win10 Migrate apps to the Universal Windows Platform (UWP)

    https://msdn.microsoft.com/en-us/library/mt148501.aspx

  5. 使用 .NET 平台,如何玩转 Universal Windows 应用?

    2015年7月30日 本文作者是 Managed Languages 团队项目经理 Lucian Wischik. 不久前,Visual Studio 2015上新增 Windows 10 应用的开发 ...

  6. 如何使用 App Studio 快速定制你自己的 Universal Windows App

    之前我为大家介绍过 App Studio 这只神器可以帮助大家快速制作一个 Windows Phone 8 的应用,今天之所以在写一篇关于 App Studio 的文章是因为,App Studio 经 ...

  7. 怎样使用 App Studio 高速定制你自己的 Universal Windows App

    今天之所以在写一篇关于 App Studio 的文章是由于,App Studio 经过了几次升级功能得到了明显提升还能够调用系统功能了.而且能够更方便的和应用商店关联公布 Universal Wind ...

  8. 详解 UWP (通用 Windows 平台) 中的两种 HttpClient API

    UWP (通用 Windows 平台) 应用开发者在构建通过 HTTP 与 Web 服务或服务器断点交互的应用时,有多种 API 可以选择.要在一个托管 UWP 应用中实现 HTTP 客户端角色,最常 ...

  9. Windows 下的高 DPI 应用开发(UWP / WPF / Windows Forms / Win32)

    本文将介绍 Windows 系统中高 DPI 开发的基础知识.由于涉及到坐标转换,这种转换经常发生在计算的不知不觉中:所以无论你使用哪种 Windows 下的 UI 框架进行开发,你都需要了解这些内容 ...

随机推荐

  1. 结合阿里云服务器,设置家中jetson tk1随时远程登陆

    前提条件: 1.路由配置dmz主机为tk1的ip ,设置路由器中ssh 端口22的访问权限 2.有一台远程服务器,服务器安装了php可以运行php文件(我使用的是阿里云) 家中tk1配置: 脚本pyt ...

  2. 原子操作--ARM架构

    说明:内核版本号为3.10.101 一.ARM架构中的原子操作实现 在原子操作(一)中我们已经提到,各个架构组织为“复仇者”联盟,统一了基本的原子变量操作,这里我们就拿atomic_dec(v)来看看 ...

  3. window下flask开发环境搭建

    1.安装python 官网下载https://www.python.org/downloads/,按提示安装就行,记住安装目录,把它添加到系统path中. 2.安装pip 官网下载pip文件:http ...

  4. 题目:利用条件运算符的嵌套来完成此题:学习成绩>=90分的同学用A表示,60-89分之间的用B表示,60分以下的用C表示。

    public class Five_05 { public static void main(String[] args) { Scanner input=new Scanner(System.in) ...

  5. Web调试利器OpenWindow

    有些时候调试web页面,在循环里面我们不方便设置断点进行调试,或者调试起来比较麻烦,我们就可以用openWindow的方法打印出想要查看的信息,既方便又省时. 代码如下: OpenWindow = w ...

  6. Bootstrap 折叠(Collapse)插件

    折叠(Collapse)插件可以很容易地让页面区域折叠起来.无论您用它来创建折叠导航还是内容面板,它都允许很多内容选项. 如果您想要单独引用该插件的功能,那么您需要引用 collapse.js.同时, ...

  7. IT小喇叭-企业品牌宣传、产品营销推广的首选

    IT小喇叭-企业品牌宣传.产品营销推广的首选 IT小喇叭,成立于2015年6月初,成都芮嘉科技有限公司旗下产品,主要进行媒体资源整合.宣传报道:使移动互联网等相关企业的产品宣传.品牌营销变得更加方便. ...

  8. Spring学习笔记 6. 尚硅谷_佟刚_Spring_Bean 之间的关系

    1,继承关系 首先从简单的代码来看,有一个Address类,配置文件有两个bean (1)Address类 package com.zsq; public class Address { privat ...

  9. 在 Mac OS 上使用 TypeScript 编写 ASP.NET Core 1.0 应用

    var appInsights=window.appInsights||function(config){ function r(config){t[config]=function(){var i= ...

  10. JSF中使用jquery拦截ajax请求

    jsf提供一个内置的jsf.ajax.request方法给我们使用,如果在jquery中使用,则需要做一些更改.  此处因为使用jquery,所以可以不必在控件中添加onclick方法了,可以给控件配 ...