引言

上一篇文章中,我们主要讲解了如何在保证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. mybatis中表与表之间的关联

    第三天 1.mybatis处理表与表之间的关系? 比如要在帖子回复表里显示其它两张相关联表的信息. 处理的第一种方式: 1)主要的数据实体类是ReplyInfo,相关联的实体表的数据是TitleInf ...

  2. jQuery基础_2

    属性:attr: 属性 , 元素.attr("属性名");获取属性attr("attr","value"): 设置属性attr({value ...

  3. mysql无法登录

    很久没用root账户登录mysql发现无法登录 以为root密码被修改 修改root密码后还是无法登录 判断ip没权限 运行 Grant all privileges on *.* to 'root' ...

  4. Unsupported major.minor version 51.0解决方法

    jdk1.6工程中使用外部jar包中类出现:Unsupported major.minor version 51.0 问题原因:外部jar包使用jdk1.7(jdk7)编译,而使用此jar包的工程jd ...

  5. checked属性

    使用checked属性,你可以设置复选按钮和单选按钮默认被选中. 为此,只需在input元素中添加属性checked <input type="radio" name=&qu ...

  6. WordPress访问打开速度很慢的几种解决方法

    最近WordPress网站访问特别的慢,有时间要加载一分钟才能完全打开,最初怀疑是服务器的问题,经过多方测试,还是没找到原因.后来,通过工具测出浏览器一直在加载fonts.googleapis.com ...

  7. TestNG教程

    TestNG教程 http://www.yiibai.com/testng/2013/0916311.html TestNG,3种执行方式: 1.ant(build.xml) 2.Eclipse(安装 ...

  8. Python-变量

    1.Python的变量是什么 变量是用来存储计算机程序中的信息,唯一的目的是将数据存储在内存中. 2.Python变量的组成 变量由字母.数字.下划线组成: 变量的第一位不能是数字,可以是字母或下划线 ...

  9. WCF服务配置问题

      上一篇中,我们主要是使用了代码来实现服务的自我寄宿.代码的实现稍微复杂些,不过还有些使用配置文件和配置工具的方法.下面来一一介绍下.     1.配置文件.首先在Host下添加个app.confi ...

  10. 基于SpringMVC的增删改查

    废话不多说,直接开始步骤! 1.创建一个Dynamic Web Project 2.在WEB-INF包下的lib文件夹中引入相关jar commons-logging-.jar jstl.jar sp ...