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