【问题标题】:How to setup a grid as template for an Items control?如何将网格设置为 Items 控件的模板?
【发布时间】:2013-05-11 21:16:01
【问题描述】:

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

基本上,我想要以下内容,但不知何故在 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> 

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

(我将 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>

【问题讨论】:

  • @Rachel's Grid Attached Properties 的完美用例
  • 我不确定这将如何工作,因为我的示例中的一个项目同时包含标题和内容。
  • 发挥你的想象力,伙计。否则,请给我一个小时左右的时间来完成我的工作,我可以为您创建一个示例。
  • @HighCore 提到的 Grid AttachedProperties 适用于动态行数,但它不适用于您尝试执行的其余操作。请参阅my answer below 了解更多详细信息。 :)
  • 评论您的工作示例;不需要设置ItemsPanelTemplate,因为StackPanel 无论如何都是默认值。您可以通过将Grid.IsSharedSizeScope="True" 直接设置为ItemsControl 来稍微简化您的解决方案。

标签: wpf grid itemscontrol itemssource


【解决方案1】:

ItemsControl 存在多个问题:

  • 让您的第一列与最大项目的宽度相匹配
  • 生成动态行数
  • 为ItemsControl 的每次迭代生成多个项目

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

<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> 

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

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

<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> 

【讨论】:

  • 请注意,Grid.IsSharedScope="True" 应该设置在父容器上,而不是子网格上。这个(否则非常好和有帮助的)答案让我对 IsSharedScope 属性感到困惑。
【解决方案2】:

你可以使用 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>

ColumnHeaderContainerStyle 隐藏了 GridViewHeader

【讨论】:

  • 谢谢,但我真的不想要列滑块或列表视图中存在的选择
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多