WrapPanel as ItemPanel for ItemsControl

烂漫一生 提交于 2019-12-17 07:24:54

问题


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

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:

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

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

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.

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?


回答1:


You might want to take a look at the ItemsPanel property:

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>



回答2:


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

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



回答3:


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"

More info here: https://wpf.2000things.com/tag/issharedsizescope/ + On ItemsControl virutualization for performance: 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>


来源:https://stackoverflow.com/questions/3131919/wrappanel-as-itempanel-for-itemscontrol

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!