zoukankan      html  css  js  c++  java
  • 重新想象 Windows 8 Store Apps (12) 控件之 GridView 特性: 拖动项, 项尺寸可变, 分组显示

    [源码下载]


    重新想象 Windows 8 Store Apps (12) - 控件之 GridView 特性: 拖动项, 项尺寸可变, 分组显示



    作者:webabcd


    介绍
    重新想象 Windows 8 Store Apps 之 GridView

    • 拖动项 - 在 GridView 内拖动 item 以对 item 排序, 拖动 item 到 GridView 外的指定位置以删除 item
    • 项尺寸可变 - 指定 GirdView 中每个 item 所占尺寸
    • 分组显示 - 分组显示集合数据



    示例
    1、演示如何在 GridView 内拖动 item 以对 item 排序,以及如何拖动 item 到 GridView 外的指定位置以删除 item
    GridView/DragItem.xaml

    <Page
        x:Class="XamlDemo.Controls.GridView.DragItem"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:XamlDemo.Controls.GridView"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
    
        <Page.Resources>
            <DataTemplate x:Key="ItemTemplate">
                <StackPanel Orientation="Vertical">
                    <TextBlock TextWrapping="Wrap" FontSize="14.667" Text="{Binding Name}" HorizontalAlignment="Left" />
                    <TextBlock TextWrapping="Wrap" FontSize="14.667" Text="{Binding Age}" HorizontalAlignment="Left"/>
                </StackPanel>
            </DataTemplate>
            <Style x:Key="ItemContainerStyle"  TargetType="GridViewItem">
                <Setter Property="Width" Value="292" />
                <Setter Property="Height" Value="80" />
                <!--
                    即使将 Margin 设置为“0”,也无法去掉 item 之间的 margin
                    如果想要去掉 item 之间的 margin,请将此 Margin 属性设置为“-4”
                -->
                <Setter Property="Margin" Value="0" />
                <Setter Property="Background" Value="Blue" />
            </Style>
            <ItemsPanelTemplate x:Key="ItemsPanel">
                <!--
                    注:WrapGrid 继承了 VirtualizingPanel,而 VariableSizedWrapGrid 并未继承 VirtualizingPanel
                -->
                <WrapGrid MaximumRowsOrColumns="3" Orientation="Vertical" VerticalChildrenAlignment="Top" HorizontalChildrenAlignment="Left" />
            </ItemsPanelTemplate>
        </Page.Resources>
    
        <Grid Background="Transparent">
            <StackPanel Margin="120 0 0 0">
    
                <TextBlock Name="lblMsg" FontSize="14.667" Text="通过拖动 GirdView 中的 Item 进行排序" />
    
                <GridView x:Name="gridView" VerticalAlignment="Top" Margin="0 10 10 0" BorderThickness="1" BorderBrush="Red" Background="LightBlue"
                          ItemTemplate="{StaticResource ItemTemplate}"
                          ItemContainerStyle="{StaticResource ItemContainerStyle}"
                          ItemsPanel="{StaticResource ItemsPanel}"
                          IsSwipeEnabled="True" IsItemClickEnabled="True"
                          CanDragItems="True" CanReorderItems="True" AllowDrop="True" 
                          DragItemsStarting="gridView_DragItemsStarting_1" />
    
                <!--拖动 item 到此处以删除 item-->
                <Grid Name="gridDelete" Margin="0 10 0 0" AllowDrop="True" Drop="gridDelete_Drop_1" DragEnter="gridDelete_DragEnter_1" DragLeave="gridDelete_DragLeave_1" DragOver="gridDelete_DragOver_1">
                    <Rectangle Width="300" Height="100" StrokeThickness="1" StrokeDashArray="2" Stroke="Red" Fill="Blue" />
                    <TextBlock FontSize="26.667" Text="拖动到此处以删除" TextAlignment="Center" VerticalAlignment="Center" />
                </Grid>
                
            </StackPanel>
        </Grid>
    </Page>

    GridView/DragItem.xaml.cs

    /*
     * 演示如何在 GridView 内拖动 item 以对 item 排序,以及如何拖动 item 到 GridView 外的指定位置以删除 item
     * 
     * GridView - 网格控件
     *     CanDragItems - item 是否可被拖动
     *     CanReorderItems - 是否可通过拖动 item 来排序
     *     AllowDrop - 是否可在 GridView 中 drop
     *     DragItemsStarting - item 开始被拖动时所触发的事件(事件参数 DragItemsStartingEventArgs)
     *      
     * DragItemsStartingEventArgs
     *     Items - 被拖动的 items 集合
     *     Cancel - 是否取消拖动操作
     *     Data - 一个 DataPackage 类型的对象,用于传递数据(与 DataPackage 在剪切板和 Share Contract 中的作用一样)
     *     
     * 
     * 注:
     * drag-drop 间传递数据,clipboard 间传递数据,Share Contract 间传递数据,以及其他场景的数据传递均可通过 DataPackage 类型的对象来完成
     * 本例没有通过 DataPackage 来传递数据(太麻烦),而是通过一个私有字段来传递数据(比较简单)
     */
    
    using System.Collections.ObjectModel;
    using Windows.UI.Xaml.Controls;
    using System.Linq;
    using XamlDemo.Model;
    using Windows.UI.Xaml;
    using System.Diagnostics;
    
    namespace XamlDemo.Controls.GridView
    {
        public sealed partial class DragItem : Page
        {
            // 数据源
            private ObservableCollection<Employee> _dataSource;
            // 拖动中的 Employee 对象
            private Employee _draggingEmployee;
    
            public DragItem()
            {
                this.InitializeComponent();
                
                // 绑定数据
                _dataSource = new ObservableCollection<Employee>(TestData.GetEmployees());
                gridView.ItemsSource = _dataSource;
    
                // GridView 中的 items 发生变化时触发的事件
                gridView.ItemContainerGenerator.ItemsChanged += ItemContainerGenerator_ItemsChanged;
            }
    
            void ItemContainerGenerator_ItemsChanged(object sender, Windows.UI.Xaml.Controls.Primitives.ItemsChangedEventArgs e)
            {
                if (e.OldPosition.Index > -1)
                {
                    // 在 GridView 中 drop 了 item,且排序发生了变化
    
                    var oldIndex = _dataSource.IndexOf(_draggingEmployee); // 被拖动的 Employee 对象的原位置
                    var newIndex = e.Position.Index + e.Position.Offset; // 被拖动的 Employee 对象的新位置
    
                    // 修改数据源
                    _dataSource.Move(oldIndex, newIndex);
    
                    _draggingEmployee = null;
                }
                
            }
    
            // GridView 中的 item 开始被拖动时
            private void gridView_DragItemsStarting_1(object sender, DragItemsStartingEventArgs e)
            {
                _draggingEmployee = e.Items.First() as Employee;
            }
    
    
            // GridView 中的 item 被 drop 到了指定的位置后
            private void gridDelete_Drop_1(object sender, DragEventArgs e)
            {
                // 从数据源中删除指定的 Employee 对象
                _dataSource.Remove(_draggingEmployee);
                _draggingEmployee = null;
    
                // 在 gridDelete 放下了拖动项
                Debug.WriteLine("Drop");
            }
    
            private void gridDelete_DragEnter_1(object sender, DragEventArgs e)
            {
                // 拖动项被拖进 gridDelete 了
                Debug.WriteLine("DragEnter");
            }
    
            private void gridDelete_DragLeave_1(object sender, DragEventArgs e)
            {
                // 拖动项被拖出 gridDelete 了
                Debug.WriteLine("DragLeave");
            }
    
            private void gridDelete_DragOver_1(object sender, DragEventArgs e)
            {
                // 拖动项在 gridDelete 上面拖动着
                Debug.WriteLine("DragOver");
            }
        }
    }


    2、演示如何指定 GirdView 中每个 item 所占尺寸
    GridView/ColorModel.cs

    using Windows.UI.Xaml.Media;
    
    namespace XamlDemo.Controls.GridView
    {
        /// <summary>
        /// 用于绑定到 VariableSized.xaml 中的 GridView 的数据实体模型
        /// </summary>
        class ColorModel
        {
            public string ColorName { get; set; }
            public SolidColorBrush ColorValue { get; set; }
    
            // 此对象所占的网格的列合并数
            public int ColSpan { get; set; }
            // 此对象所占的网格的行合并数
            public int RowSpan { get; set; }
        }
    }

    GridView/MyGridView.cs

    /*
     * 此控件可以指定 GridView 的每个 item 所占网格的列合并数和行合并数
     */
    
    using System;
    using System.Diagnostics;
    
    namespace XamlDemo.Controls.GridView
    {
        public class MyGridView : Windows.UI.Xaml.Controls.GridView
        {
            protected override void PrepareContainerForItemOverride(Windows.UI.Xaml.DependencyObject element, object item)
            {
                try
                {
                    // 指定 VariableSizedWrapGrid 的 ColumnSpan 和 RowSpan
    
                    dynamic dynamicItem = item;
                    element.SetValue(Windows.UI.Xaml.Controls.VariableSizedWrapGrid.ColumnSpanProperty, dynamicItem.ColSpan);
                    element.SetValue(Windows.UI.Xaml.Controls.VariableSizedWrapGrid.RowSpanProperty, dynamicItem.RowSpan);
                }
                catch(Exception ex)
                {
                    // 当有异常情况发生时(比如:item 没有 ColSpan 属性或 RowSpan 属性)
    
                    Debug.WriteLine(ex.ToString());
    
                    element.SetValue(Windows.UI.Xaml.Controls.VariableSizedWrapGrid.ColumnSpanProperty, 1);
                    element.SetValue(Windows.UI.Xaml.Controls.VariableSizedWrapGrid.RowSpanProperty, 1);
                }
                finally
                {
                    base.PrepareContainerForItemOverride(element, item);
                }
            }
        }
    }

    GridView/VariableSized.xaml

    <Page
        x:Class="XamlDemo.Controls.GridView.VariableSized"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:XamlDemo.Controls.GridView"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
    
        <Page.Resources>
            <DataTemplate x:Key="ItemTemplate">
                <Grid Background="{Binding ColorValue}">
                    <Grid Background="Black" VerticalAlignment="Top" HorizontalAlignment="Stretch" Opacity="0.7">
                        <TextBlock Text="{Binding ColorName}" />
                    </Grid>
                </Grid>
            </DataTemplate>
            <Style x:Key="ItemContainerStyle" TargetType="GridViewItem">
                <Setter Property="VerticalContentAlignment" Value="Stretch" />
                <Setter Property="HorizontalContentAlignment" Value="Stretch" />
                <!--
                    即使将 Margin 设置为“0”,也无法去掉 item 之间的 margin
                    如果想要去掉 item 之间的 margin,请将此 Margin 属性设置为“-4”
                -->
                <Setter Property="Margin" Value="-4" />
            </Style>
            <ItemsPanelTemplate x:Key="ItemsPanel">
                <!--
                    注:WrapGrid 继承了 VirtualizingPanel,而 VariableSizedWrapGrid 并未继承 VirtualizingPanel
                
                    ItemWidth, ItemHeight - 每个网格的宽和高
                    ColumnSpan, RowSpan - item 所在网格的列合并数和行合并数,本例在后台指定了这两个属性,参见 MyGridView.cs
                -->
                <VariableSizedWrapGrid MaximumRowsOrColumns="4" Orientation="Vertical" ItemWidth="100" ItemHeight="100" Height="400" />
            </ItemsPanelTemplate>
    
        </Page.Resources>
    
        <Grid Background="Transparent">
            <StackPanel Margin="120 0 0 0">
    
                <!--
                    使用 MyGridView 控件,其重写了 GridView 的 PrepareContainerForItemOverride() 方法,详见 MyGridView.cs
                -->
                <local:MyGridView x:Name="gridView" Height="400" VerticalAlignment="Top" Margin="0 10 10 0" Background="Yellow"
                                  ItemTemplate="{StaticResource ItemTemplate}"
                                  ItemContainerStyle="{StaticResource ItemContainerStyle}"
                                  ItemsPanel="{StaticResource ItemsPanel}" 
                                  IsItemClickEnabled="False" IsSwipeEnabled="False" SelectionMode="None"
                                  ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Auto">
                </local:MyGridView>
    
            </StackPanel>
        </Grid>
    </Page>

    GridView/VariableSized.xaml.cs

    /*
     * 演示如何指定 GirdView 中每个 item 所占尺寸
     * GridView 是一个网格控件,这里所谓的每个 item 所占尺寸,其本质上就是 item 所在网格的列合并数和行合并数
     * 
     * 要实现此需求的话:
     * 1、必须使用 VariableSizedWrapGrid,具体见 VariableSized.xaml
     * 2、需要重写 GridView 的 PrepareContainerForItemOverride() 方法,具体见 MyGridView.cs
     */
    
    using System.Reflection;
    using System.Linq;
    using System.Collections.Generic;
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Media;
    using System;
    using Windows.UI;
    
    namespace XamlDemo.Controls.GridView
    {
        public sealed partial class VariableSized : Page
        {
            public VariableSized()
            {
                this.InitializeComponent();
    
                BindData();
            }
    
            private void BindData()
            {
                Random random = new Random();
    
                // 获取 Windows.UI.Colors 的全部数据
                List<ColorModel> colors = typeof(Colors)  // typeof 在 System.Reflection 命名空间下
                    .GetRuntimeProperties()
                    .Select(c => new ColorModel
                    {
                        ColorName = c.Name,
                        ColorValue = new SolidColorBrush((Color)c.GetValue(null)),
                        ColSpan = random.Next(1, 3), // 此对象所占网格的列合并数
                        RowSpan = random.Next(1, 3) // 此对象所占网格的行合并数
                    })
                    .ToList();
    
                // 绑定数据
                gridView.ItemsSource = colors;
            }
        }
    }


    3、演示如何分组显示集合数据(关于分组的示例会和之后的 SemanticZoom 一起写)
    GridView/Group.xaml

    <Page
        x:Class="XamlDemo.Controls.GridView.Group"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:XamlDemo.Controls.GridView"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
    
        <Grid Background="Transparent">
            <StackPanel Margin="120 0 0 0">
    
                <TextBlock Name="lblMsg" FontSize="14.667">
                    <Run>关于 GridView 的分组显示请参见本 app 的索引页 Index.xaml 和 Index.xaml.cs</Run>
                    <LineBreak />
                    <Run>分组的功能来源于 ItemsControl(GridView, ListView, FlipView, ListBox 等均继承了 ItemsControl)</Run>
                </TextBlock>
    
            </StackPanel>
        </Grid>
    </Page>



    OK
    [源码下载]

  • 相关阅读:
    @RequestParam注解使用:Name for argument type [java.lang.String] not available, and parameter name information not found in class file either.
    cglib动态代理导致注解丢失问题及如何修改注解允许被继承
    springboot Autowired BeanNotOfRequiredTypeException
    git根据用户过滤提交记录
    不同包下,相同数据结构的两个类进行转换
    How to use Jackson to deserialise an array of objects
    jooq实践
    java如何寻找main函数对应的类
    Python--matplotlib
    Python 和 Scikit-Learn
  • 原文地址:https://www.cnblogs.com/webabcd/p/2965362.html
Copyright © 2011-2022 走看看