响应式GridView

时间:2015-07-17 13:33:25

标签: windows-store-apps winrt-xaml

我想为我的Windows Universal应用创建一个响应式 GridView 。我基本上想要一个 GridView ,这些列水平填充整个空间。

Responsive GridView wireframe

XAML应该是这样的,但我不知道我必须使用 ItemsPanelTemplate 的哪个组合。

<Page>

<Page.Resources>
    <CollectionViewSource x:Name="groupedItemsViewSource" IsSourceGrouped="true"/>
</Page.Resources>

<GridView ItemsSource="{Binding Source={StaticResource groupedItemsViewSource}}">
    <GridView.ItemsPanel>
        <ItemsPanelTemplate>
            <!-- ? -->
        </ItemsPanelTemplate>
    </GridView.ItemsPanel>
    <GridView.GroupStyle>
        <GroupStyle>
            <GroupStyle.HeaderTemplate>
                <DataTemplate>
                    <!-- header -->
                </DataTemplate>
            </GroupStyle.HeaderTemplate>
            <GroupStyle.Panel>
                <ItemsPanelTemplate>
                    <!-- ? -->
                </ItemsPanelTemplate>
            </GroupStyle.Panel>
        </GroupStyle>
    </GridView.GroupStyle>
    <GridView.ItemTemplate>
        <DataTemplate>
            <!-- item -->
        </DataTemplate>
    </GridView.ItemTemplate>
</GridView>

</Page>

1 个答案:

答案 0 :(得分:1)

我理解你的问题。老实说,你可能不会以这种方式做到这一点。但也许你只是想学习如何去做。因此,为了学术探究,我将回答你的问题。

使用此XAML:

<local:MyGridView>

    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition />
                    <RowDefinition />
                    <RowDefinition />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition />
                    <ColumnDefinition />
                    <ColumnDefinition />
                </Grid.ColumnDefinitions>
            </Grid>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>

    <ItemsControl.ItemContainerStyle>
        <Style TargetType="GridViewItem">
            <Setter Property="HorizontalContentAlignment" Value="Stretch" />
            <Setter Property="VerticalContentAlignment" Value="Stretch" />
        </Style>
    </ItemsControl.ItemContainerStyle>

    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Grid   Background="{Binding Color}"
                Margin="10"
                Grid.RowSpan="{Binding RowSpan}" 
                Grid.ColumnSpan="{Binding ColumnSpan}"
                Grid.Row="{Binding Row}" 
                Grid.Column="{Binding Column}">
            </Grid>
        </DataTemplate>
    </ItemsControl.ItemTemplate>

    <GridView.Items>
        <local:MyItem Color="Gainsboro" Row="0" RowSpan="1" Column="0" ColumnSpan="3" />
        <local:MyItem Color="Red" Row="1" RowSpan="1" Column="0" ColumnSpan="1" />
        <local:MyItem Color="Green" Row="1" RowSpan="1" Column="1" ColumnSpan="1" />
        <local:MyItem Color="Blue" Row="1" RowSpan="1" Column="2" ColumnSpan="1" />
        <local:MyItem Color="Yellow" Row="2" RowSpan="1" Column="0" ColumnSpan="1" />
        <local:MyItem Color="Orange" Row="2" RowSpan="1" Column="1" ColumnSpan="1" />
    </GridView.Items>

</local:MyGridView>

使用此代码:

public class MyGridView : GridView
{
    protected override DependencyObject GetContainerForItemOverride()
    {
        var container = base.GetContainerForItemOverride() as FrameworkElement;
        if (container == null) return container;

        var content = ItemTemplate.LoadContent() as FrameworkElement;
        if (content == null) return container;

        // sync the container grid dependency properties with the content
        var binding = content.GetBindingExpression(Grid.RowProperty);
        if (binding != null)
            container.SetBinding(Grid.RowProperty, content.GetBindingExpression(Grid.RowProperty).ParentBinding);
        binding = content.GetBindingExpression(Grid.RowSpanProperty);
        if (binding != null)
            container.SetBinding(Grid.RowSpanProperty, binding.ParentBinding);
        binding = content.GetBindingExpression(Grid.ColumnProperty);
        if (binding != null)
            container.SetBinding(Grid.ColumnProperty, binding.ParentBinding);
        binding = content.GetBindingExpression(Grid.ColumnSpanProperty);
        if (binding != null)
            container.SetBinding(Grid.ColumnSpanProperty, binding.ParentBinding);

        return container;
    }
}

这将为您提供您在问题中所要求的内容。

现在,让我们谈谈为什么你可能不想要这种方法。单元格的动态大小不是WrapGrid的特征,GridViewGrid的原生面板。因此,我们必须切换到GridView,它没有动态行/列。我可以更新此示例以创建动态行/列吗?当然。但那不是重点。

在内部,MS Design建议您的边距会根据WrapGrid的宽度略有变化。这本身就是一个不小的壮举,因为你不能将数据绑定到边缘。但是,由此产生的视觉效果得到了很大改善,因为它可以在页面上为您提供更多空间,因为宽度会减小而不会弄乱数据项的大小。达到某个较窄的宽度后,您可以让原始GridView为您删除列,而不是保留固定数量的列。

退一步,考虑如何使用初始方法在def create @challenge = Challenge.new(challenge_params) respond_to do |format| if @challenge.save format.html { redirect_to users_path, notice: 'Challenge was successfully created.' } format.json { render :show, status: :created, location: @challenge } else format.html { render :new } format.json { render json: @challenge.errors, status: :unprocessable_entity } end end end 中使用自适应逻辑编写每个数据项。这种复杂性是大多数应用程序的不必要的补充。话虽这么说,我也不知道你的应用程序。你是开发者而不是我。您可以决定什么样的项目最佳。

你可能会问自己,微软如何改变保证金?答案是使用VSM我们等待一定宽度,当它发生时,我们明确设置边距。根据您决定使用的控件类型,您可能需要以某种方式注入边距,但一般来说,它只是一个VSM操作。这很重要,因为它不是滑动比例。也就是说,它可以是更宽的边距,也可以是更窄的边距,而且介于两者之间。

伙计,我希望这是有道理的。

祝你好运!