none
gridview中的item如何实现紧密排列 RRS feed

  • 问题

  • hi,all

    我的代码是这样子的:

    DataTemplate :

     <common:LayoutAwarePage.Resources>

            <selectphotos:SmallHeightConverter x:Key="SmallHeightConverter"/>

            <selectphotos:SmallWidthConverter x:Key="SmallWidthConverter"/>

            <selectphotos:WidthConverter x:Key="WidthConverter"/>

            <selectphotos:HeightConverter x:Key="HeightConverter"/>

            <selectphotos:ThumbConverter x:Key="ThumbConverter"/>

            <!-- TODO: Delete this line if the key AppName is declared in App.xaml -->
            <x:String x:Key="AppName">My Application</x:String>

            <DataTemplate x:Key="FolderTemplate">
                <Grid >
                    <Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}">
                        <Image Source="{Binding Converter={StaticResource ThumbConverter}}"  Width="360" Height="600" Stretch="UniformToFill"/>
                    </Border>
                    <StackPanel VerticalAlignment="Bottom" Background="{StaticResource ListViewItemOverlayBackgroundThemeBrush}">
                        <TextBlock Text="{Binding stName}" Foreground="{StaticResource ListViewItemOverlayForegroundThemeBrush}"
             Height="80" Margin="15,0,15,0" FontSize="48" TextAlignment="Center"/>
                    </StackPanel>
                </Grid>
            </DataTemplate>

            <DataTemplate x:Key="ImageGalleryDataTemplate">
                <Grid VerticalAlignment="Center" HorizontalAlignment="Center" Background="#FFCB3434" ScrollViewer.VerticalScrollBarVisibility="Disabled" Height="800" PointerWheelChanged="grid_wheel" Loaded="load"  >
                    <Image Stretch="Fill"
            Source="{Binding Converter={StaticResource ThumbConverter}}"
            Width="{Binding Converter={StaticResource WidthConverter}}"
            Height="{Binding Converter={StaticResource HeightConverter}}"
            HorizontalAlignment="Center" VerticalAlignment="Center" />
                </Grid>
            </DataTemplate>


            <local:FileFolderInformationTemplateSelector x:Key="FileFolderInformationTemplateSelector"
          FileInformationTemplate="{StaticResource ImageGalleryDataTemplate}"
          FolderInformationTemplate="{StaticResource FolderTemplate}" />


            <DataTemplate x:Key="FolderTemplateSmall">
                <Grid>
                    <Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}">
                        <Image Source="{Binding Converter={StaticResource ThumbConverter}}"  Width="200" Height="140" Stretch="UniformToFill"/>
                    </Border>
                    <StackPanel VerticalAlignment="Bottom" Background="{StaticResource ListViewItemOverlayBackgroundThemeBrush}">
                        <TextBlock Text="{Binding stName}" Foreground="{StaticResource ListViewItemOverlayForegroundThemeBrush}"
             Height="30" Margin="15,0,15,0" FontSize="24" TextAlignment="Center"/>
                    </StackPanel>
                </Grid>
            </DataTemplate>

            <DataTemplate x:Key="ImageGalleryDataTemplateSmall">
                <Grid VerticalAlignment="Stretch" HorizontalAlignment="Stretch"  ScrollViewer.VerticalScrollBarVisibility="Disabled" ScrollViewer.HorizontalScrollBarVisibility="Visible" Background="{x:Null}"  >
                    <Image Stretch="Fill"
            Source="{Binding Converter={StaticResource ThumbConverter}}"
            Width="{Binding Converter={StaticResource SmallWidthConverter}}"
            Height="{Binding Converter={StaticResource SmallHeightConverter}}"
            HorizontalAlignment="Center" VerticalAlignment="Center" />
                </Grid>
            </DataTemplate>


            <local:FileFolderInformationTemplateSelector x:Key="FileFolderInformationTemplateSelectorSmall"
          FileInformationTemplate="{StaticResource ImageGalleryDataTemplateSmall}"
          FolderInformationTemplate="{StaticResource FolderTemplateSmall}" />


            <CollectionViewSource
          x:Name="itemsViewSource"/>

        </common:LayoutAwarePage.Resources>

    gridview:

     <SemanticZoom x:Name="semanticZoom"  Grid.Row="1" IsZoomedInViewActive="True"  VerticalAlignment="Bottom" PointerWheelChanged="wheel" ViewChangeCompleted="viewchange_end" ViewChangeStarted="viewchange_begin" >
                <SemanticZoom.ZoomedOutView>
                    <GridView
                         AutomationProperties.AutomationId="ItemGridView"
                         AutomationProperties.Name="Items"
             
                         Margin="0,-4,0,0"
                         Padding="30,0"
               
                         ItemTemplateSelector="{StaticResource FileFolderInformationTemplateSelectorSmall}"
                         SelectionMode="Multiple" ItemClick="item_click" IsItemClickEnabled="True" HorizontalContentAlignment="Stretch" />
                </SemanticZoom.ZoomedOutView>
                <SemanticZoom.ZoomedInView>

                    <GridView
                         AutomationProperties.AutomationId="ItemGridView"
                         AutomationProperties.Name="Items"
            
                         Margin="0,-4,0,0"
                         Padding="30,0"
               
                         ItemTemplateSelector="{StaticResource FileFolderInformationTemplateSelector}"
                         SelectionMode="Multiple" ItemClick="item_click" IsItemClickEnabled="True" Foreground="{x:Null}" PointerWheelChanged="gridview_wheel"/>
                     
                </SemanticZoom.ZoomedInView>
            </SemanticZoom>

    我的gridview绑定了一个数据模版,数据模版的宽高设定的时自动,运行以后,gridview的item大小总是固定的,和第一个加载的item的大小一样。但是我想要的结果是每个item的宽高和绑定的数据源的宽高一样。不知道怎样修改?

    还请各位高人指点。

    2012年6月14日 12:36

答案

  • 你用 VariableSizedWrapGrid 作为你的ItemsPanel,然后根据Item去指定 VariableSizedWrapGrid.ColumnSpan 和 VariableSizedWrapGrid.RowSpan的值,我写了一个例子,你参考一下。

    XAML:

    <Page
        x:Class="App21.MainPage"
        IsTabStop="false"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:App21"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
        <Page.Resources>
            <Style x:Key="gridviewitemstyle" TargetType="GridViewItem">
                <Setter Property="Background" Value="Red"/>
            </Style>
            <Style x:Key="style1x1" TargetType="GridViewItem" 
                   BasedOn="{StaticResource gridviewitemstyle}">
                <Setter Property="VariableSizedWrapGrid.ColumnSpan" Value="1"/>
                <Setter Property="VariableSizedWrapGrid.RowSpan" Value="1"/>
                <Setter Property="Width" Value="100"/>
                <Setter Property="Height" Value="100"/>
            </Style>
            <Style x:Key="style2x2" TargetType="GridViewItem" 
                   BasedOn="{StaticResource gridviewitemstyle}">
                <Setter Property="VariableSizedWrapGrid.ColumnSpan" Value="2"/>
                <Setter Property="VariableSizedWrapGrid.RowSpan" Value="2"/>
                <Setter Property="Width" Value="200"/>
                <Setter Property="Height" Value="200"/>
            </Style>
            <Style x:Key="style2x1" TargetType="GridViewItem" 
                   BasedOn="{StaticResource gridviewitemstyle}">
                <Setter Property="VariableSizedWrapGrid.ColumnSpan" Value="2"/>
                <Setter Property="VariableSizedWrapGrid.RowSpan" Value="1"/>
                <Setter Property="Width" Value="200"/>
                <Setter Property="Height" Value="100"/>
            </Style>
            <Style x:Key="style1x2" TargetType="GridViewItem" 
                   BasedOn="{StaticResource gridviewitemstyle}">
                <Setter Property="VariableSizedWrapGrid.ColumnSpan" Value="1"/>
                <Setter Property="VariableSizedWrapGrid.RowSpan" Value="2"/>
                <Setter Property="Width" Value="100"/>
                <Setter Property="Height" Value="200"/>
            </Style>
    
            <local:MyStyleSelector x:Key="setyselector"
                style1x1="{StaticResource style1x1}"
                style1x2="{StaticResource style1x2}"
                style2x1="{StaticResource style2x1}"
                style2x2="{StaticResource style2x2}"/>
        </Page.Resources>
        <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
            <GridView ItemsSource="{Binding}" ItemContainerStyleSelector="{StaticResource setyselector}">
                <GridView.ItemsPanel>
                    <ItemsPanelTemplate>
                        <VariableSizedWrapGrid MaximumRowsOrColumns="2" Orientation="Vertical" ItemHeight="100" ItemWidth="100"/>
                    </ItemsPanelTemplate>
                </GridView.ItemsPanel>
                <GridView.ItemTemplate>
                    <DataTemplate>
                        <Grid/>
                    </DataTemplate>
                </GridView.ItemTemplate>
            </GridView>
        </Grid>
    </Page>

    C#:

        public sealed partial class MainPage : Page
        {
            public MainPage()
            {
                this.InitializeComponent();
    
                this.DataContext = new ObservableCollection<Item>()
                {
                    new Item (){ContainerStyle=1},
                    new Item (){ContainerStyle=1},
                    new Item (){ContainerStyle=2},
                    new Item (){ContainerStyle=1},
                    new Item (){ContainerStyle=1},
                    new Item (){ContainerStyle=4},
                    new Item (){ContainerStyle=3},
                    new Item (){ContainerStyle=1},
                    new Item (){ContainerStyle=1}
                };
            }
    
            /// <summary>
            /// Invoked when this page is about to be displayed in a Frame.
            /// </summary>
            /// <param name="e">Event data that describes how this page was reached.  The Parameter
            /// property is typically used to configure the page.</param>
            protected override void OnNavigatedTo(NavigationEventArgs e)
            {
            }
        }
    
        public class MyStyleSelector : StyleSelector
        {
            public Style style1x1 { get; set; }
            public Style style1x2 { get; set; }
            public Style style2x1 { get; set; }
            public Style style2x2 { get; set; }
            protected override Style SelectStyleCore(object item, DependencyObject container)
            {
                if (item != null && item is Item)
                {
                    Item i = item as Item;
                    switch (i.ContainerStyle)
                    {
                        case 1: return style1x1;
                        case 2: return style1x2;
                        case 3: return style2x1;
                        case 4: return style2x2;
                    }
                }
                return base.SelectStyleCore(item, container);
            }
        }
    
        public class Item
        {
            public int ContainerStyle { get; set; }
            // 1:1x1 
            // 2:1x2
            // 3:2x1
            // 4:2x2
        }

    效果图:


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us


    2012年6月20日 8:51
    版主

全部回复

  • 这样的话,你应该通过修改 ItemContainerStyle 或者 ItemContainerStyleSelector 来对GridViewItem制定不同的样式,然后在GridViewItem的样式中设置/绑定其高 宽值。 因为一个ItemsControl 通过 ItemsPanel 来呈现一个个Item的ItemContainer, GridView的ItemContainer就是GridViewItem。 然后在 GridViewItem 中才是你具体的数据模板定义的样式元素。


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us

    2012年6月15日 7:42
    版主
  • 请问通过修改 ItemContainerStyle 来设置宽高值,是不是一次性的。我试了一下,代码如下:

         <GridView.ItemContainerStyle>
                    <Style TargetType="GridViewItem">
                        <Setter Property="Width" Value="{Binding Converter={StaticResource WidthConverter}}"/>
                        <Setter Property="Height" Value="740" />
                   
                    </Style>
                </GridView.ItemContainerStyle>

    结果是width值为绑上去的第一个item的width值。以后所有的item.width都是这个值。这样等于没有解决我的问题。请问我这样修改ItemContainerStyle 对不对?

    2012年6月19日 9:00
  • 这样设置就是针对GridView中所有的ItemContainer设置了,你需要通过 ItemContainerStyleSelector  来实现,针对不同的Item来返回不同的Container样式。具体用法与TemplateSelector类似,需要自己实现一个类型, 然后在类型中判断当前的Item 并且返回对应的Style, 你可以参考http://social.msdn.microsoft.com/Forums/zh-CN/metroappzhcn/thread/20fa16c7-a383-464d-aba1-cc61326f094d 来看看TemplateSelector怎么实现的。


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us

    2012年6月19日 9:19
    版主
  • 谢谢你,我现在已经可以显示出不一样尺寸的图片了,但是还没有达到紧密排列的效果。我预想的效果是这样的:

    而我现在的效果是这样的:

    我现在的代码:

    <Style x:Key="ShortItemSmall" TargetType="GridViewItem">
                <Setter Property="Width" Value="100" />
                <Setter Property="Height" Value="140" />
            </Style>

            <Style x:Key="NormalItemSmall" TargetType="GridViewItem">
                <Setter Property="Width" Value="200" />
                <Setter Property="Height" Value="140" />
            </Style>

            <Style x:Key="LongItemSmall" TargetType="GridViewItem">
                <Setter Property="Width" Value="400" />
                <Setter Property="Height" Value="140" />
            </Style>

            <local:FileFolderInformationStyleSelector x:Key="FileFolderInformationStyleSelectorSmall"
          ShortStyle="{StaticResource ShortItemSmall}"
          NormalStyle="{StaticResource NormalItemSmall}"
                LongStyle="{StaticResource LongItemSmall}"/>

    请问,这个问题怎么解决?

    2012年6月20日 3:17
  • 你用 VariableSizedWrapGrid 作为你的ItemsPanel,然后根据Item去指定 VariableSizedWrapGrid.ColumnSpan 和 VariableSizedWrapGrid.RowSpan的值,我写了一个例子,你参考一下。

    XAML:

    <Page
        x:Class="App21.MainPage"
        IsTabStop="false"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:App21"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
        <Page.Resources>
            <Style x:Key="gridviewitemstyle" TargetType="GridViewItem">
                <Setter Property="Background" Value="Red"/>
            </Style>
            <Style x:Key="style1x1" TargetType="GridViewItem" 
                   BasedOn="{StaticResource gridviewitemstyle}">
                <Setter Property="VariableSizedWrapGrid.ColumnSpan" Value="1"/>
                <Setter Property="VariableSizedWrapGrid.RowSpan" Value="1"/>
                <Setter Property="Width" Value="100"/>
                <Setter Property="Height" Value="100"/>
            </Style>
            <Style x:Key="style2x2" TargetType="GridViewItem" 
                   BasedOn="{StaticResource gridviewitemstyle}">
                <Setter Property="VariableSizedWrapGrid.ColumnSpan" Value="2"/>
                <Setter Property="VariableSizedWrapGrid.RowSpan" Value="2"/>
                <Setter Property="Width" Value="200"/>
                <Setter Property="Height" Value="200"/>
            </Style>
            <Style x:Key="style2x1" TargetType="GridViewItem" 
                   BasedOn="{StaticResource gridviewitemstyle}">
                <Setter Property="VariableSizedWrapGrid.ColumnSpan" Value="2"/>
                <Setter Property="VariableSizedWrapGrid.RowSpan" Value="1"/>
                <Setter Property="Width" Value="200"/>
                <Setter Property="Height" Value="100"/>
            </Style>
            <Style x:Key="style1x2" TargetType="GridViewItem" 
                   BasedOn="{StaticResource gridviewitemstyle}">
                <Setter Property="VariableSizedWrapGrid.ColumnSpan" Value="1"/>
                <Setter Property="VariableSizedWrapGrid.RowSpan" Value="2"/>
                <Setter Property="Width" Value="100"/>
                <Setter Property="Height" Value="200"/>
            </Style>
    
            <local:MyStyleSelector x:Key="setyselector"
                style1x1="{StaticResource style1x1}"
                style1x2="{StaticResource style1x2}"
                style2x1="{StaticResource style2x1}"
                style2x2="{StaticResource style2x2}"/>
        </Page.Resources>
        <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
            <GridView ItemsSource="{Binding}" ItemContainerStyleSelector="{StaticResource setyselector}">
                <GridView.ItemsPanel>
                    <ItemsPanelTemplate>
                        <VariableSizedWrapGrid MaximumRowsOrColumns="2" Orientation="Vertical" ItemHeight="100" ItemWidth="100"/>
                    </ItemsPanelTemplate>
                </GridView.ItemsPanel>
                <GridView.ItemTemplate>
                    <DataTemplate>
                        <Grid/>
                    </DataTemplate>
                </GridView.ItemTemplate>
            </GridView>
        </Grid>
    </Page>

    C#:

        public sealed partial class MainPage : Page
        {
            public MainPage()
            {
                this.InitializeComponent();
    
                this.DataContext = new ObservableCollection<Item>()
                {
                    new Item (){ContainerStyle=1},
                    new Item (){ContainerStyle=1},
                    new Item (){ContainerStyle=2},
                    new Item (){ContainerStyle=1},
                    new Item (){ContainerStyle=1},
                    new Item (){ContainerStyle=4},
                    new Item (){ContainerStyle=3},
                    new Item (){ContainerStyle=1},
                    new Item (){ContainerStyle=1}
                };
            }
    
            /// <summary>
            /// Invoked when this page is about to be displayed in a Frame.
            /// </summary>
            /// <param name="e">Event data that describes how this page was reached.  The Parameter
            /// property is typically used to configure the page.</param>
            protected override void OnNavigatedTo(NavigationEventArgs e)
            {
            }
        }
    
        public class MyStyleSelector : StyleSelector
        {
            public Style style1x1 { get; set; }
            public Style style1x2 { get; set; }
            public Style style2x1 { get; set; }
            public Style style2x2 { get; set; }
            protected override Style SelectStyleCore(object item, DependencyObject container)
            {
                if (item != null && item is Item)
                {
                    Item i = item as Item;
                    switch (i.ContainerStyle)
                    {
                        case 1: return style1x1;
                        case 2: return style1x2;
                        case 3: return style2x1;
                        case 4: return style2x2;
                    }
                }
                return base.SelectStyleCore(item, container);
            }
        }
    
        public class Item
        {
            public int ContainerStyle { get; set; }
            // 1:1x1 
            // 2:1x2
            // 3:2x1
            // 4:2x2
        }

    效果图:


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us


    2012年6月20日 8:51
    版主
  • 谢谢你,在你的帮助下我总算是解决了这个问题啦~

    另外追问一下,itemcontainer和itemspanel,这两者的概念我有点混淆,能不能解释一下?

    2012年6月20日 12:43
  • 接着问一个问题

    如果我更新了GridView 的数据源,怎么让DataTemplate 的模版也随着 数据源的变得而变得

    我的意思是 如果让 数据来决定 DataTemplate (多次加载)

    2012年8月13日 9:55
  • StyleSelector中的 SelectStyleCore方法参数的第一 item就是你的数据源对象,你数据源变了,只要在这个方法里面能够根据你变化的数据返回你需要的DataTemplate就可以了,这里就是数据决定DataTemplate 模版

    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us

    2012年8月14日 8:28
    版主