wpf 如何将网格设置为 Items 控件的模板?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16596579/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 08:48:47  来源:igfitidea点击:

How to setup a grid as template for an Items control?

wpfgriditemscontrolitemssource

提问by pastillman

I'm trying to create an ItemsControlthat uses a grid as its ItemsPanelin such a way that it has two columns, where the first columns width is the width of the widest item in that column, and has as may rows needed to display all the items

我正在尝试创建一个ItemsControl使用网格作为它ItemsPanel的方式,它有两列,其中第一列的宽度是该列中最宽项目的宽度,并且具有显示所有项目所需的行

Basically, I want the following, but somehow within an ItemsControlso that I can bind to a collection of objects:

基本上,我想要以下内容,但以某种方式在一个范围内,ItemsControl以便我可以绑定到一组对象:

<Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="auto"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>

        <Grid.RowDefinitions>
            <RowDefinition Height="auto"/>
            <RowDefinition Height="auto"/>
            <RowDefinition Height="auto"/>
        </Grid.RowDefinitions>

        <Label Content="{Binding Items[0].Header}"/>
        <TextBox Text="{Binding Items[0].Content}" Grid.Column="1"/>

        <Label Content="{Binding Items[1].Header}" Grid.Row="1"/>
        <TextBox Text="{Binding Items[1].Content}" Grid.Row="1" Grid.Column="1"/>

        <Label Content="{Binding Items[2].Header}" Grid.Row="2"/>
        <TextBox Text="{Binding Items[2].Content}" Grid.Row="2" Grid.Column="1"/>
    </Grid> 

Edit : Rachels answer worked great, here is a working example.

编辑:Rachels 的回答效果很好,这是一个工作示例。

(I moved the Grid.IsSharedSizeScope="True" to the ItemsPanel, not sure if Rachel meant to put it in the ItemTemplate (which didn't work))

(我将 Grid.IsSharedSizeScope="True" 移到了 ItemsPanel,不确定 Rachel 是否打算将它放在 ItemTemplate 中(这不起作用))

namespace WpfApplication23
{
    public partial class Window1 : Window
    {
        public List<Item> Items { get; set; }

        public Window1()
        {
            Items = new List<Item>() 
            { 
                new Item(){ Header="Item0", Content="someVal" },
                new Item(){ Header="Item1", Content="someVal" },
                new Item(){ Header="Item267676", Content="someVal" },
                new Item(){ Header="a", Content="someVal" },
                new Item(){ Header="bbbbbbbbbbbbbbbbbbbbbbbbbb", Content="someVal" },
                new Item(){ Header="ccccccc", Content="someVal" } 
            };

            InitializeComponent();

            DataContext = this;
        }
    }

    public class Item
    {
        public string Header { get; set; }
        public string Content { get; set; }
    }
}

<Window x:Class="WpfApplication23.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <ItemsControl ItemsSource="{Binding Items}">

        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel Grid.IsSharedSizeScope="True"/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>

        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition SharedSizeGroup="ColumnOne" />
                        <ColumnDefinition Width="*" />
                    </Grid.ColumnDefinitions>
                    <Label Content="{Binding Header}"/>
                    <TextBox Text="{Binding Content}" Grid.Column="1"/>
                </Grid>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Window>

回答by Rachel

There are multiple problems here for an ItemsControl:

这里有多个问题ItemsControl

  • Getting your first column to match the width of the largest item
  • Generating a dynamic number of rows
  • Generating more than one item for each iteration of the ItemsControl
  • 使您的第一列与最大项目的宽度相匹配
  • 生成动态行数
  • 为每次迭代生成多个项目 ItemsControl

The last one is really the biggest problem, because an ItemsControlwraps each ItemTemplatein a ContentPresenter, so there is no default way of creating more than one item in the panel for each Iteration of the ItemsControl. Your end result would look like this:

最后一个确实是最大的问题,因为 anItemsControl将每个都包装ItemTemplate在 a 中ContentPresenter,因此没有默认方法可以为 的每次迭代在面板中创建多个项目ItemsControl。您的最终结果将如下所示:

<Grid>
    ...

    <ContentPresenter>
        <Label Content="{Binding Items[0].Header}"/>
        <TextBox Text="{Binding Items[0].Content}" Grid.Column="1"/>
    </ContentPresenter>
    <ContentPresenter>
        <Label Content="{Binding Items[1].Header}" Grid.Row="1"/>
        <TextBox Text="{Binding Items[1].Content}" Grid.Row="1" Grid.Column="1"/>
    </ContentPresenter>
    <ContentPresenter>
        <Label Content="{Binding Items[2].Header}" Grid.Row="2"/>
        <TextBox Text="{Binding Items[2].Content}" Grid.Row="2" Grid.Column="1"/>
    </ContentPresenter>
</Grid> 

My best suggestion would be to create an ItemTemplatethat contains a 1x2 Grid, and use Grid.IsSharedSizeScopeto make the width of the first column shared. (The ItemsPanelTemplatewould remain the default StackPanel.)

我最好的建议是创建一个ItemTemplate包含 1x2 的Grid,并用于Grid.IsSharedSizeScope使第一列的宽度共享。(ItemsPanelTemplate将保持默认StackPanel。)

This way, the end result would look like this:

这样,最终结果将如下所示:

<StackPanel>
    <ContentPresenter>
        <Grid IsSharedSizeScope="True">
            <Grid.ColumnDefinitions>
                <ColumnDefinition SharedSizeGroup="ColumnOne" />
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>
            <Label Content="{Binding Header}"/>
            <TextBox Text="{Binding Content}" Grid.Column="1"/>
        </Grid>
    </ContentPresenter>
    <ContentPresenter>
        <Grid IsSharedSizeScope="True">
            <Grid.ColumnDefinitions>
                <ColumnDefinition SharedSizeGroup="ColumnOne" />
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>
            <Label Content="{Binding Header}"/>
            <TextBox Text="{Binding Content}" Grid.Column="1"/>
        </Grid>
    </ContentPresenter>
    ...
</StackPanel> 

回答by Smotsch

You can use a ListView

您可以使用 ListView

<ListView ItemsSource="{Binding MyList}">
    <ListView.View>
        <GridView>
            <GridView.ColumnHeaderContainerStyle>
                <Style TargetType="{x:Type GridViewColumnHeader}">
                    <Setter Property="Visibility" Value="Collapsed" />
                </Style>
            </GridView.ColumnHeaderContainerStyle>
            <GridViewColumn 
                Header="" 
                Width="Auto" 
                DisplayMemberBinding="{Binding Header}"/>
            <GridViewColumn 
                Header="" 
                DisplayMemberBinding="{Binding Value}"/>
        </GridView>
    </ListView.View>
</ListView>

the ColumnHeaderContainerStyle hides the GridViewHeader

ColumnHeaderContainerStyle 隐藏了 GridViewHeader