WrapPanel 作为 ItemsControl 的 ItemPanel

Posted

技术标签:

【中文标题】WrapPanel 作为 ItemsControl 的 ItemPanel【英文标题】:WrapPanel as ItemPanel for ItemsControl 【发布时间】:2011-03-09 02:19:55 【问题描述】:

我仍然在使用 WPF 并边走边学。现在尝试构建控件的动态分组(主要是按钮,但可能包括复选框和其他)。

我不知道最好的方法是什么,所以我尝试创建一个 ItemsControl 样式,然后将这些项目添加到 WrapPanel 内的 ItemsPresenter 中。很快意识到这些项目不会包装,因为它们实际上不在 WrapPanel 内,除非我把它作为 ItemsHost。像这样:

<Style x:Key="ButtonPanelGroup" TargetType="x:Type ItemsControl">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="x:Type ItemsControl">
                <Border CornerRadius="5"
                        BorderBrush="StaticResource DarkColorBrush"
                        BorderThickness="1"
                        Margin="5">
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition />
                            <RowDefinition Height="Auto" />
                        </Grid.RowDefinitions>

                        <WrapPanel IsItemsHost="True" FlowDirection="LeftToRight">
                            <ItemsPresenter />
                        </WrapPanel>

                        <ContentPresenter ContentSource="Name" Grid.Row="1" />

                    </Grid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

请注意,这是一项正在进行的工作,我仍然需要实现许多样式效果。我在这里使用它:

<UniformGrid Rows="1">
    <ItemsControl Name="Group1" Style="StaticResource ButtonPanelGroup">
        <Button>Button1</Button>
        <Button>Button2</Button>
        <CheckBox>TickBox</CheckBox>
    </ItemsControl>

    <ItemsControl Name="Group2" Style="StaticResource ButtonPanelGroup">
        <Button>Button3</Button>
        <Button>Button4</Button>
        <Button>Button5</Button>
    </ItemsControl>

    <ItemsControl Name="Group3" Style="StaticResource ButtonPanelGroup">
        <Button>Button6</Button>
        <Button>Button7</Button>
        <Button>Button8</Button>
    </ItemsControl>
</UniformGrid>

另外请注意,它仍在进行中,因为 UniformGrid 不是这里的方法,而且边距可能会很痛苦(是否有重叠的边距?),因此将不胜感激。

现在是真正的问题。这不起作用我得到一个错误:

“ItemsPresenter”对象无法添加到“WrapPanel”。不能 显式修改用作 ItemsPanel 的 Panel 的 Children 集合 项目控制。 ItemsControl 为 Panel 生成子元素。错误 在对象'System.Windows.Controls.ItemsPresenter'。

那么做这样的事情的最好方法是什么(希望能够将按钮和其他控件扔到 ItemControl 中,并且排队真的很好)。将控件放入某种集合并进行迭代会更好吗?

很想把它做好,但我的 WPF 技能仍然缺乏。是否有任何 WPF 书籍可以教授基础知识并展示专业人士如何真正做到这一点?

【问题讨论】:

【参考方案1】:

您可能想查看ItemsPanel 属性:

获取或设置定义控制项目布局的面板的模板。

例子:

<ItemsControl>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <WrapPanel />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>

您可以将其设置为样式,如下所示:

<Style TargetType="ItemsControl">
    <Setter Property="ItemsPanel">
      <Setter.Value>
            <ItemsPanelTemplate>
                <WrapPanel />
            </ItemsPanelTemplate>
        </Setter.Value>
    </Setter>
</Style>

【讨论】:

这行得通,但我不想将它设置为样式而不是每个 ItemsControl。我认为 IsItemsHost 属性可以做到这一点,但似乎不起作用。这是唯一的方法吗? 使用 ItemsControl 样式更新答案 啊当然我也可以加入这种风格,谢谢。如果你有时间,你可以看看我还有两个尚未解决的问题。 ***.com/questions/3118266/…***.com/questions/3004967/how-to-reuse-layouts-in-wpf 还有一个问题,我将放入使用此样式的 ItemsControl 的所有项目都将从 ContentControl 继承,我可以在某处设置它们的默认属性(如边距等),因此我只需要设置一次,或者最好说如果是按钮使用这种样式,复选框使用这种等等? 当然。只需将具有适当 TargetType 的样式放入 ItemsControl 的资源字典 (ItemsControl.Resources)。【参考方案2】:

不要忘记线索属性 IsItemsHost="True" 的定义。 否则,您的 ItemsControl 将不会显示您的项目。

<ListBox ItemsSource="Binding MyItemsSource">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate >
                <WrapPanel IsItemsHost="True"/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
    </ListBox>

【讨论】:

IsItemsHost="True" 不是必需的 @kux,试着去掉这个属性看看会发生什么 我试过了,不然不会写到这里。删除,它仍然有效。 prnt.sc/va06yi【参考方案3】:

这是慢速 DataGrid / xceed datagrid 和 WrapPanel 解决方案的另一个简单替代方案。当大量数据或整个表格仅用于编辑时可能很有用。 使用 ItemsControl + Grid.IsSharedSizeScope="True"

更多信息在这里:https://wpf.2000things.com/tag/issharedsizescope/ + 关于 ItemsControl 虚拟化性能:Virtualizing an ItemsControl?

<Grid Grid.IsSharedSizeScope="True" Margin="0,30,0,0">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition MinWidth="50" Width="Auto" SharedSizeGroup="Id" />
            <ColumnDefinition MinWidth="50" Width="Auto" SharedSizeGroup="Time"  />
        </Grid.ColumnDefinitions>
        <Border Grid.Column="0" >
            <TextBlock VerticalAlignment="Center" TextWrapping="NoWrap" Text="Header1" />
        </Border>
        <Border Grid.Column="1" >
            <TextBlock VerticalAlignment="Center" TextWrapping="NoWrap" Text="Header2" />
        </Border>
    </Grid>

    <ItemsControl Grid.Row="1" ItemsSource="Binding RunInstance.ConcentrationGradient.Steps">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition MinWidth="50" Width="Auto" SharedSizeGroup="Id" />
                        <ColumnDefinition MinWidth="50" Width="Auto" SharedSizeGroup="Time" />
                    </Grid.ColumnDefinitions>
                    <Border Grid.Column="0">
                        <TextBlock VerticalAlignment="Center" TextWrapping="NoWrap" Text="Binding Index, Mode=OneWay, UpdateSourceTrigger=PropertyChanged" />
                    </Border>
                     <Border Grid.Column="1">
                        <TextBlock VerticalAlignment="Center" TextWrapping="NoWrap" Text="Binding Time, Mode=OneWay, UpdateSourceTrigger=PropertyChanged" />
                    </Border>
                </Grid>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Grid>

【讨论】:

以上是关于WrapPanel 作为 ItemsControl 的 ItemPanel的主要内容,如果未能解决你的问题,请参考以下文章

WPF: WrapPanel 容器的模板数据绑定(ItemsControl)

将 WrapPanel 用作 ItemsPanel 的 ItemsControl - 结合“静态”子项和 ItemsSource

WPF - 如何在 WrapPanel 中居中所有项目?

WPF实现竖向排列并换行显示

#400 – 使用ItemsPanel 属性将WrapPanel 作为ListBox的显示面板(Using a WrapPanel as the Items Panel for a ListBox)(

WPF: WrapPanel 容器的数据绑定(动态生成控件遍历)