引言

上一篇文章中,我们主要讲解了如何在保证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:  <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)平台的更多相关文章

  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. Linux下Hadoop2.6.0集群环境的搭建

    本文旨在提供最基本的,可以用于在生产环境进行Hadoop.HDFS分布式环境的搭建,对自己是个总结和整理,也能方便新人学习使用. 基础环境 JDK的安装与配置 现在直接到Oracle官网(http:/ ...

  2. JS各种算法小例子

    <!DOCTYPE html><html><head>    <title>js</title>    <meta charset=& ...

  3. 自己对Extjs的Xtemplate的忽略

    之前学习extjs Xtmeplate受一些书籍的误导,说Xtemplate不支持else ,今天仔细看了官网的示例,才恍然大悟,卧槽!不仅支持if-elseif-else结构 连switch都能够支 ...

  4. vs2013卸载后重新安装不能用了,如何解决

    vs2013卸载后重新安装不能用了 据说VS卸载后有残留文件,估计是注册文件没删除,弄了很多方法,最后只有重装.你可以下载一个cclearn清理注册表,再装试试 我卸载完用360清理了一下 之后再安装 ...

  5. 百度贴吧python吧抓取用户名和图片

    原理就是将贴吧条数中的用户提取出来并在此爬取用户中的图片 #!/usr/bin/env python #coding:utf-8 import requests import urllib2 impo ...

  6. swift3.0:associatedtype

    E文:https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Lang ...

  7. switch的经典引用

    #include<stdio.h> int main(void) { int i; do{ printf("按1,流量查询\n"); printf("按2,人 ...

  8. flex进行页面的基础布局

    接触flex有一段时间了,由于自己在移动上的经验比较少,一直以为这个和css3的其他属性差不多,就是一个盒模型的缩放之类的.今天一个移动的小项目用到了这个属性,仔细看了下,先不说里面具体的属性,就fl ...

  9. H264与RTP

    http://blog.163.com/laorenyuhai126@126/blog/static/1935077920111218152989/

  10. XStream学习笔记

    XStream 所需jar包: xstream-1.3.jar xpp3_min-1.1.4c.jar xmlpull-1.1.3.1.jar 目录: 1.注解去除,标签中带有包名的节点 2.注解修改 ...