views:

63

answers:

1

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 effectivly 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 uniform grid wouldn't be the way to go here and also margins can be a pain ( are there any margins that overlap? ) so input tehre would be appriciated.

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?

+3  A: 

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>
Arcturus
That works but I wan't to set it at the style instead of at every ItemsControl. I thought that was possible with the IsItemsHost property but doesn't seem to work.Is this the only way?
Ingó Vals
Updated answer with a Style for ItemsControl
Arcturus
Ah of course I can also just add into this style, thank you.If you have time you could look at 2 other questions I have that are still unresolved.http://stackoverflow.com/questions/3118266/wpf-datatemplate-property-set-at-contenthttp://stackoverflow.com/questions/3004967/how-to-reuse-layouts-in-wpf
Ingó Vals
And another questions, all the items I will put into my ItemsControl that uses this Style will inherit from ContentControl, can I somewhere set the default properties of them ( like margin and such ) so I only need to set it once, or better yet say that if it's a button use this style, checkbox use this and so on?
Ingó Vals
Sure. Just put styles with the appropriate TargetType into the ItemsControl's resource dictionary (ItemsControl.Resources).
Robert Rossney
It will always look up the most specific style.. So if you define it for ContentControl, it will also be for Button. But if you have both, the Button rules out the ContentControl style. You should also take a look at the BasedOn property of Style: http://www.switchonthecode.com/tutorials/wpf-the-basedon-style-property
Arcturus