wpf WrapPanel 作为 ItemsControl 的 ItemPanel

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3131919/
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-08 21:53:56  来源:igfitidea点击:

WrapPanel as ItemPanel for ItemsControl

wpfstylesitemscontrolitemspanelitemspresenter

提问by Ingó Vals

Still fooling around with WPF and learning as I go. Trying now to build a dynamic grouping of controls (mostly Buttons but might include CheckBoxes and others).

仍然在玩 WPF 并边学习边学习。现在尝试构建一个动态的控件分组(主要是按钮,但可能包括复选框等)。

I had no idea what was the best way to do this so I tried creating a ItemsControl style and then add the items into a ItemsPresenter inside a WrapPanel. Soon realized the items wouldn't wrap because they effectively weren't inside the WrapPanel unless I put it as ItemsHost. Like this:

我不知道这样做的最佳方法是什么,所以我尝试创建一个 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>

Note that this is a work in progress and there are many styling effects I still need to implement. Here I use it:

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

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

Also note here that it is still a work in progress as UniformGrid wouldn't be the way to go here and also margins can be a pain (are there any margins that overlap?) so input there would be appreciated.

还要注意,它仍然是一项正在进行的工作,因为 UniformGrid 不会成为这里的方法,而且边距也可能是一个痛苦(是否有任何边距重叠?)所以输入将不胜感激。

Now to the real problem. This doesn't work I get a error:

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

'ItemsPresenter' object cannot be added to 'WrapPanel'. Cannot explicitly modify Children collection of Panel used as ItemsPanel for ItemsControl. ItemsControl generates child elements for Panel. Error at object 'System.Windows.Controls.ItemsPresenter'.

无法将“ItemsPresenter”对象添加到“WrapPanel”。无法显式修改用作 ItemsControl 的 ItemsPanel 的 Panel 的 Children 集合。ItemsControl 为 Panel 生成子元素。对象“System.Windows.Controls.ItemsPresenter”出错。

So what's the best way to do something like this ( would love to be able to just throw buttons and other controls into the ItemControl and the line up real nice ). Would it be better to put the Controls into a collection of some kind and iterate.

那么做这样的事情的最佳方法是什么(希望能够将按钮和其他控件放入 ItemControl 并且排列非常好)。将控件放入某种集合并进行迭代会更好。

Would love to get it nicely done but my WPF skills are still lacking. Are there any WPF books that teach beyond the basics and show how pro's would really do it?

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

回答by Arcturus

You might want to take a look at the ItemsPanelproperty:

您可能需要查看ItemsPanel属性:

Gets or sets the template that defines the panel that controls the layout of items.

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

Example:

例子:

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

And you can set it in a Style as follows:

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

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

回答by Mr.B

Don't forget definition of clue property IsItemsHost="True". Otherwise your ItemsControl won't show your items.

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

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

回答by Evalds Urtans

Here's another simple alternative to slow DataGrid / xceed datagrid and WrapPanel solution. Might be useful when a lot of data or whole table is just for editing. Using ItemsControl + Grid.IsSharedSizeScope="True"

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

More info here: https://wpf.2000things.com/tag/issharedsizescope/+ On ItemsControl virutualization for performance: Virtualizing an ItemsControl?

更多信息在这里:https: //wpf.2000things.com/tag/issharedsizescope/ + 关于 ItemsControl虚拟化性能:虚拟化 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>