GridView控件特性: 拖動項, 項尺寸可變, 分組顯示
介紹
重新想象 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
[源碼下載]:http://files.cnblogs.com/webabcd/Windows8.rar