引言

上一篇文章中,我们主要讲解了如何在保证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. 一 java线程的等待/通知模型

    java 中线程之间的通信问题,有这么一个模型:一个线程修改了一个对象的值,而另一个线程感知到了变化,然后进行相应的操作,整个过程开始于一个线程,而最终执行又是另一个线程.前者是生产者,后者就是消费者 ...

  2. ZOJ3792_Romantic Value

    给出图,使得两点无流量,剩余其他边的总容量与删除边数的比值. 要机智啊... 因为原图给的边数不超过1000,容量也不超过1000,可以这样把边的容量变为2000*c+1.这样跑出最大流后,最大流除以 ...

  3. mybatis框架中分页的实现

    2.分页的实现? 分页的时候考虑的问题: 分页的大小,分页的索引. 比如:分页的大小为10,分页的起始索引为1(索引从1开始) 第一页:1到10.    起始行号: (页的索引-1)*分页大小+1 结 ...

  4. C# 通过身份证查询出生日期

    private int GetAgeBycode(string b_car_code) { string birthday = ""; //处理18位的身份证号码从号码中得到生日和 ...

  5. project 2016 11 20 树的多项式

    #include <iostream>#include <stack>#include <cmath>#include <sstream> using ...

  6. java 实现多个文件的Zip包的生成

    最近在项目中遇到多个文件的达成Zip包,由于对这块不熟,在网上找到一个,现在忘了找的谁的,如果您发现了,请告诉我你的链接,我指明出处 下面是相关代码: package run.utils; impor ...

  7. u3d avatar部件的理解

    u3d中带动画的fbx文件导入的时候,就会显示一个avatar组件,这个到底干嘛的一直没能很好的理解,翻看网上的介绍,基本都是告诉你,设置humanoid类型动画时,拖拉过去之类,但是这玩意到底存储了 ...

  8. iOS进阶_地图上定位的标志——大头针

    一.添加大头针 地图使用的框架是MapKit 大头针走的是MKAnnotation协议 /* 注意:因为是满足协议MKAnnotation,所以没有MKAnnotation的系统大头针类,必须自定义大 ...

  9. windows IIS6 PHP搭建

    windows下搭建PHP环境有很多种方法.传说,FastCGI下运行PHP  是 兼顾安全和效率的一种.传说.传说.下面讲解在windows server2003 IIS6中安装 PHP 以下文字, ...

  10. iOS开发零基础--Swift教程 字符串的利用

    字符串的介绍 字符串在任何的开发中使用都是非常频繁的 OC和Swift中字符串的区别 在OC中字符串类型时NSString,在Swift中字符串类型是String OC中字符串@"" ...