W10新闻应用程序如何拉伸gridview中的项目?

Arn*_*tte 19 c# xaml gridview

我正在尝试在Windows 10中的默认新闻应用程序中创建一个gridview.据我所知,我必须为ItemSeight设置VariableSizedWrapGrid的ItemWidth.但是它不会拉伸项目以适应整个网格宽度,而新闻应用程序确实这样做,如下图所示.他们是怎么做到的?它是一种特殊的自定义控件吗? 宽屏,4列和物品都很宽

Narrowscreen,3个小柱子

Sir*_*ufo 9

我会给你一个概念:

+---------+ +---------+ +---------+ 
|  small  | |         | |         |
+---------+ |         | |         |
--- gap --- | medium  | |         |
+---------+ |         | |         |
|  small  | |         | |   big   |
+---------+ +---------+ |         |
--- gap --- --- gap --- |         |
+---------+ +---------+ |         |
|  small  | |  small  | |         |
+---------+ +---------+ +---------+
--- gap --- --- gap --- --- gap ---

所以我们只有3个不同的盒子用于具有已知高度的呈现.视图本身可以决定(代码隐藏)使用哪个模板来呈现内容.

  • 小:带有小缩略图的标题
  • 中:带标题的小图像
  • 大:带标题的图像和文章中的一些文字

Alle项目按每组5至9项分组排列.这些组在ItemsControl中呈现,每个组由WrapPanel(垂直oriantation)呈现.

让我们看看有些行:

  • 2列,6项
lllll  mmmmm
lllll  mmmmm
lllll  mmmmm
lllll
lllll  sssss

lllll  mmmmm
lllll  mmmmm
lllll  mmmmm
lllll
lllll  sssss
  • 3列,6项
lllll  lllll  mmmmm
lllll  lllll  mmmmm
lllll  lllll  mmmmm
lllll  lllll  
lllll  lllll  lllll
              lllll
mmmmm  mmmmm  lllll
mmmmm  mmmmm  lllll
mmmmm  mmmmm  lllll
  • 4列,6项
lllll  lllll  lllll  sssss
lllll  lllll  lllll
lllll  lllll  lllll  sssss
lllll  lllll  lllll
lllll  lllll  lllll  sssss
  • 5列,6项
mmmmm  mmmmm  mmmmm  mmmmm  sssss
mmmmm  mmmmm  mmmmm  mmmmm
mmmmm  mmmmm  mmmmm  mmmmm  sssss

因此,我们需要三个DataTemplates用于内容项,一些模板用于WrapPanel,一些逻辑用于视图内部,用于将项目分组为行,以及WrapPanel和内部项目的模板管理.

这里有一个简单的XAML PoC来测试这个概念:

<Grid>
    <ScrollViewer>
        <ItemsControl>
            <ItemsControl.Resources>
                <Style x:Key="col" TargetType="WrapPanel">
                    <Setter Property="Orientation" Value="Vertical"/>
                    <Setter Property="ItemWidth" Value="80"/>
                </Style>

                <Style x:Key="content" TargetType="Border">
                    <Setter Property="Margin" Value="5,5"/>
                </Style>
                <Style x:Key="small" TargetType="Border" BasedOn="{StaticResource content}">
                    <Setter Property="Background" Value="Orange"/>
                    <Setter Property="Height" Value="30"/>
                </Style>
                <Style x:Key="medium" TargetType="Border" BasedOn="{StaticResource content}">
                    <Setter Property="Background" Value="Green"/>
                    <Setter Property="Height" Value="70"/>
                </Style>
                <Style x:Key="large" TargetType="Border" BasedOn="{StaticResource content}">
                    <Setter Property="Background" Value="Red"/>
                    <Setter Property="Height" Value="110"/>
                </Style>

                <Style x:Key="2col6items" TargetType="WrapPanel" BasedOn="{StaticResource col}">
                    <Setter Property="Height" Value="240"/>
                </Style>

                <Style x:Key="3col6items" TargetType="WrapPanel" BasedOn="{StaticResource col}">
                    <Setter Property="Height" Value="200"/>
                </Style>

                <Style x:Key="4col6items" TargetType="WrapPanel" BasedOn="{StaticResource col}">
                    <Setter Property="Height" Value="120"/>
                </Style>

                <Style x:Key="5col6items" TargetType="WrapPanel" BasedOn="{StaticResource col}">
                    <Setter Property="Height" Value="80"/>
                </Style>


            </ItemsControl.Resources>
            <!-- first row -->
            <WrapPanel Style="{StaticResource 5col6items}">
                <Border Style="{StaticResource medium}"/>
                <Border Style="{StaticResource medium}"/>
                <Border Style="{StaticResource medium}"/>
                <Border Style="{StaticResource medium}"/>
                <Border Style="{StaticResource small}"/>
                <Border Style="{StaticResource small}"/>
            </WrapPanel>
            <!-- second row -->
            <WrapPanel Style="{StaticResource 4col6items}">
                <Border Style="{StaticResource large}"/>
                <Border Style="{StaticResource large}"/>
                <Border Style="{StaticResource large}"/>
                <Border Style="{StaticResource small}"/>
                <Border Style="{StaticResource small}"/>
                <Border Style="{StaticResource small}"/>
            </WrapPanel>
            <!-- third row -->
            <WrapPanel Style="{StaticResource 3col6items}">
                <Border Style="{StaticResource large}"/>
                <Border Style="{StaticResource medium}"/>
                <Border Style="{StaticResource large}"/>
                <Border Style="{StaticResource medium}"/>
                <Border Style="{StaticResource medium}"/>
                <Border Style="{StaticResource large}"/>
            </WrapPanel>
            <!-- fourth row -->
            <WrapPanel Style="{StaticResource 2col6items}">
                <Border Style="{StaticResource large}"/>
                <Border Style="{StaticResource large}"/>
                <Border Style="{StaticResource medium}"/>
                <Border Style="{StaticResource small}"/>
                <Border Style="{StaticResource medium}"/>
                <Border Style="{StaticResource small}"/>
            </WrapPanel>
        </ItemsControl>
    </ScrollViewer>
</Grid>
Run Code Online (Sandbox Code Playgroud)

和相似的

在此输入图像描述

更新

一个非常简单的 ProofOfConcept,在调整大小时进行拉伸和模板化

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <ScrollViewer>
            <ItemsControl x:Name="ItemsPresenter" SizeChanged="ItemsPresenter_SizeChanged">
                <ItemsControl.Resources>
                    <Style x:Key="col" TargetType="WrapPanel">
                        <Setter Property="Orientation" Value="Vertical"/>
                        <Setter Property="ItemWidth" Value="{Binding ColumnWidth, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MainWindow}}}"/>
                    </Style>

                    <Style x:Key="content" TargetType="TextBlock">
                        <Setter Property="Margin" Value="5"/>
                        <Setter Property="HorizontalAlignment" Value="Stretch"/>
                        <Setter Property="TextAlignment" Value="Center"/>
                        <Setter Property="VerticalAlignment" Value="Stretch"/>
                    </Style>
                    <Style x:Key="small" TargetType="TextBlock" BasedOn="{StaticResource content}">
                        <Setter Property="Background" Value="LightBlue"/>
                        <Setter Property="Height" Value="30"/>
                    </Style>
                    <Style x:Key="medium" TargetType="TextBlock" BasedOn="{StaticResource content}">
                        <Setter Property="Background" Value="LightGreen"/>
                        <Setter Property="Height" Value="70"/>
                    </Style>
                    <Style x:Key="large" TargetType="TextBlock" BasedOn="{StaticResource content}">
                        <Setter Property="Background" Value="LightSalmon"/>
                        <Setter Property="Height" Value="110"/>
                    </Style>

                    <Style x:Key="1col6items" TargetType="WrapPanel" BasedOn="{StaticResource col}">
                        <Setter Property="Height" Value="480"/>
                    </Style>

                    <Style x:Key="2col6items" TargetType="WrapPanel" BasedOn="{StaticResource col}">
                        <Setter Property="Height" Value="240"/>
                    </Style>

                    <Style x:Key="3col6items" TargetType="WrapPanel" BasedOn="{StaticResource col}">
                        <Setter Property="Height" Value="200"/>
                    </Style>

                    <Style x:Key="4col6items" TargetType="WrapPanel" BasedOn="{StaticResource col}">
                        <Setter Property="Height" Value="120"/>
                    </Style>

                    <Style x:Key="5col6items" TargetType="WrapPanel" BasedOn="{StaticResource col}">
                        <Setter Property="Height" Value="80"/>
                    </Style>


                </ItemsControl.Resources>
                <!-- first row -->
                <WrapPanel >
                    <TextBlock>1</TextBlock>
                    <TextBlock>2</TextBlock>
                    <TextBlock>3</TextBlock>
                    <TextBlock>4</TextBlock>
                    <TextBlock>5</TextBlock>
                    <TextBlock>6</TextBlock>
                </WrapPanel>
                <!-- second row -->
                <WrapPanel >
                    <TextBlock>7</TextBlock>
                    <TextBlock>8</TextBlock>
                    <TextBlock>9</TextBlock>
                    <TextBlock>10</TextBlock>
                    <TextBlock>11</TextBlock>
                    <TextBlock>12</TextBlock>
                </WrapPanel>
                <!-- third row -->
                <WrapPanel >
                    <TextBlock>13</TextBlock>
                    <TextBlock>14</TextBlock>
                    <TextBlock>15</TextBlock>
                    <TextBlock>16</TextBlock>
                    <TextBlock>17</TextBlock>
                    <TextBlock>18</TextBlock>
                </WrapPanel>
            </ItemsControl>
        </ScrollViewer>
    </Grid>
</Window>
Run Code Online (Sandbox Code Playgroud)

和代码隐藏

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent( );
    }

    public int ColumnCount
    {
        get { return (int) GetValue( ColumnCountProperty ); }
        private set { SetValue( ColumnCountProperty, value ); }
    }

    // Using a DependencyProperty as the backing store for ColumnCount.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ColumnCountProperty =
        DependencyProperty.Register( "ColumnCount", typeof( int ), typeof( MainWindow ), new PropertyMetadata( 1 ) );

    public double ColumnWidth
    {
        get { return (double) GetValue( ColumnWidthProperty ); }
        private set { SetValue( ColumnWidthProperty, value ); }
    }

    // Using a DependencyProperty as the backing store for ColumnWidth.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ColumnWidthProperty =
        DependencyProperty.Register( "ColumnWidth", typeof( double ), typeof( MainWindow ), new PropertyMetadata( (double) 100 ) );

    public double ColumnMinWidth
    {
        get { return (double) GetValue( ColumnMinWidthProperty ); }
        set
        {
            SetValue( ColumnMinWidthProperty, value );
            CalculateColumnLayout( );
        }
    }

    // Using a DependencyProperty as the backing store for ColumnMinWidth.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ColumnMinWidthProperty =
        DependencyProperty.Register( "ColumnMinWidth", typeof( double ), typeof( MainWindow ), new PropertyMetadata( (double) 200 ) );

    public double ColumnMaxWidth
    {
        get { return (double) GetValue( ColumnMaxWidthProperty ); }
        set
        {
            SetValue( ColumnMaxWidthProperty, value );
            CalculateColumnLayout( );
        }
    }

    // Using a DependencyProperty as the backing store for ColumnMaxWidth.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ColumnMaxWidthProperty =
        DependencyProperty.Register( "ColumnMaxWidth", typeof( double ), typeof( MainWindow ), new PropertyMetadata( (double) 250 ) );

    private void CalculateColumnLayout()
    {
        int colCount = ColumnCount;
        double totalWidth = ItemsPresenter.ActualWidth;
        double colWidth = totalWidth / colCount;

        while ( colCount > 1 && colWidth < Math.Min( ColumnMinWidth, ColumnMaxWidth ) )
        {
            colCount--;
            colWidth = totalWidth / colCount;
        }

        while ( colCount < 5 && colWidth > Math.Max( ColumnMinWidth, ColumnMaxWidth ) )
        {
            colCount++;
            colWidth = totalWidth / colCount;
        }

        if ( ColumnCount != colCount )
        {
            ColumnCount = colCount;
            StyleItemsPresenterItems( );
        }
        ColumnWidth = colWidth;
    }

    private Dictionary<int, string[]> _styles = new Dictionary<int, string[]>
    {
        [ 1 ] = new string[] { "medium", "medium", "medium", "medium", "medium", "medium" },
        [ 2 ] = new string[] { "large", "medium", "small", "small", "medium", "large" },
        [ 3 ] = new string[] { "large", "medium", "medium", "large", "large", "medium" },
        [ 4 ] = new string[] { "large", "large", "large", "small", "small", "small" },
        [ 5 ] = new string[] { "medium", "medium", "medium", "medium", "small", "small" },
    };


    private void StyleItemsPresenterItems()
    {
        foreach ( var pnl in ItemsPresenter.Items.OfType<WrapPanel>( ) )
        {
            if ( pnl != null )
            {
                pnl.Style = ItemsPresenter.Resources[ $"{ColumnCount}col6items" ] as Style;

                foreach ( var item in pnl.Children.OfType<TextBlock>( ).Zip( _styles[ ColumnCount ], ( border, stylename ) => new { border, stylename } ) )
                {
                    item.border.Style = ItemsPresenter.Resources[ item.stylename ] as Style;
                }

            }
        }
    }

    private void ItemsPresenter_SizeChanged( object sender, SizeChangedEventArgs e )
    {
        CalculateColumnLayout( );
    }
}
Run Code Online (Sandbox Code Playgroud)

最后结果

在此输入图像描述


Her*_*man 3

根据MSDN, ItemWidth 可以设置为 Auto。

ItemHeight和ItemWidth的默认值不是0,而是Double.NaN。ItemHeight 和 ItemWidth 支持成为未设置的“自动”值。由于 ItemHeight 和 ItemWidth 是 Double 值,因此使用 Double.NaN 作为特殊值来表示此“自动”行为。布局系统将“自动”值解释为通常意味着对象的大小应调整为布局中的可用大小,而不是特定的像素值。

我不知道这是否会导致您想要的行为。如果没有,那么您可以通过将 ItemWidth 绑定到一个属性来获取它,在该属性中您可以根据网格的宽度计算项目宽度。它看起来像这样:

float DynamicItemWidth {
  get {
    int ItemMinimumWidth = 300, margin = 16; //just some guesses
    var gridWidth = ...;

    var numberOfColumns = gridWidth % ItemMinimumWidth;
    var itemWidth = (gridWidth - margin * (numberOfColumns - 1)) / numberOfColumns;

    return itemWidth;
  }
}
Run Code Online (Sandbox Code Playgroud)