文档章节

如何将GridViewEX升级到UWP(Universal Windows Platform)平台

葡萄城技术团队
 葡萄城技术团队
发布于 2015/10/27 15:00
字数 2040
阅读 315
收藏 0

引言

 

上一篇文章中,我们主要讲解了如何在保证GridView控件的用户体验基础上,扩展GridView生成GridViewEx控件,增加动态添加新分组功能等,本文在上文的基础上,介绍如何在Windows10中使用GridViewEx,开发UWP应用。

extended GridView with grouping, variable sized items and drag and drop support

 

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: <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”控件,在拖拽过程中有简单的状态切换逻辑。

GridViewEx - 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的开发。

示例图片:

live tiles

UWP平台开发工具

ComponentOne Studio for UWP,是一套可以编写所有 UWP 平台应用的控件集,包括表格、报表、图表、仪表盘、组织图、地图、PDF、Excel、Word、日程安排、输入、导航等多个控件,有效帮助开发过程。

原文链接:http://www.codeproject.com/Articles/1037059/How-to-Upgrade-Extended-GridView-from-WinRT-to-Uni

© 著作权归作者所有

共有 人打赏支持
葡萄城技术团队

葡萄城技术团队

粉丝 370
博文 519
码字总数 752973
作品 17
西安
高级程序员
私信 提问
扩展GridView控件——为内容项添加拖放及分组功能

引言 相信大家对GridView都不陌生,是非常有用的控件,用于平铺有序的显示多个内容项。打开任何WinRT应用或者是微软合作商的网站,都会在APP中发现GridView的使用。“Tiles”提供了一个简单易...

葡萄城控件技术团队
2015/10/20
72
0
微软 Build 2016年开发者大会发布多项功能升级

微软Build 2016开发者大会在美国旧金山的莫斯康展览中心开幕。本次大会对一些重点功能进行了完善。如手写笔支持技术Windows Ink、语音识别Cortana应用集(Cortana Collection)、生物识别技术...

powertoolsteam
2016/03/31
0
0
微软再向开发者重申:UWP 是 PC 的最佳平台

微软在 Windows 10 Creators Update 更新发布的几个月前,就曾赞扬了 UWP 的好处。而现在,微软再次提醒开发人员,Universal Windows Platform(UWP,Windows 通用应用平台)真的非常重要。 ...

王练
2017/02/12
2.3K
10
使用 .NET 平台,如何玩转 Universal Windows 应用?

2015年7月30日 本文作者是 Managed Languages 团队项目经理 Lucian Wischik。 不久前,Visual Studio 2015上新增 Windows 10 应用的开发工具——Universal Windows App开发工具。这个发布拥有...

OneAPM蓝海讯通
2015/12/30
46
0
理解 .NET Platform Standard

相关博文:ASP.NET 5 Target framework dnx451 and dnxcore50 .NET Platform Standard:https://github.com/dotnet/corefx/blob/master/Documentation/architecture/net-platform-standard.m......

技术小哥哥
2016/04/19
0
0

没有更多内容

加载失败,请刷新页面

加载更多

【阿里面试系列】之前有人问过我一个这样的面试题

文章简介 很多人对Thread.join的作用以及实现了解得很少,毕竟这个api我们很少使用。这篇文章仍然会结合使用及原理进行深度分析 扩展阅读: 「阿里面试系列」搞懂并发编程,轻松应对80%的面试...

Java架构资源分享
3分钟前
0
0
CentOS 7.2 yum方式安装MySQL 5.7

CentOS 7.2 yum方式安装MySQL 5.7 CentOS 7之后的版本yum的默认源中使用MariaDB替代原先MySQL,因此安装方式较为以往有一些改变: 下载mysql的源 wget http://dev.mysql.com/get/mysql57-co...

yizhichao
3分钟前
0
0
nginx-tutorial

Nginx 本项目是一个 Nginx 极简教程,目的在于帮助新手快速入门 Nginx。 demos 目录中的示例模拟了工作中的一些常用实战场景,并且都可以通过脚本一键式启动,让您可以快速看到演示效果。 <!...

吴伟祥
4分钟前
0
0
分布式系统下的Session共享问题

分布式系统下的Session共享问题 分布式服务器有多台,用nginx做负载均衡,这样同一个IP访问同一个页面会被分配到不同的服务器上,如果session不同步的话,就会出现很多问题,比如说最常见的登...

晨猫
9分钟前
0
0
2018 中国短视频开发者创意大赛震撼来袭,万元现金大奖邀你来战!

当下,短视频 App 已成为各个年龄层最火最潮的应用,而在短视频行业发展如火如荼时,又掀起了一轮潮流新玩法的探讨,为短视频新形势下提供更多可能性。2018 年 12 月 3 日,中国短视频开发者...

七牛云
12分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部