WPF Group Style is disturbing wrap panel wrapping - wpf

I am using WrapPanel (with vertical orientation) as items panel for ItemsControl. Items are properly warpping without adding a group style. When i add a group style for items control then wrappanel is not wrapping items, all items are getting displayed vertically in a single column instead of spanning in to multiple columns. I am not using any complex layout for both group header or for ItemTemplate.
Here is the XAML source..
<Grid>
<ItemsControl ItemsSource="{Binding Items}" Grid.Row="0" ScrollViewer.VerticalScrollBarVisibility="Disabled" ScrollViewer.HorizontalScrollBarVisibility="Visible">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Vertical"
MaxHeight="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Grid}},Path=ActualHeight}"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<StackPanel>
<TextBlock FontSize="15" FontWeight="Bold" Text="{Binding Name}"/>
</StackPanel>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ItemsControl.GroupStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Name}"/>
<TextBox Text="{Binding Value}" Grid.Column="1" HorizontalAlignment="Right"></TextBox>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>

Finally figure out the problem.
When using GroupStyle we need to mention GroupStyle.Panel otherwise default panel will be used
which is a stackpanel.
The ItemsPanel which have declared as Wrappanel will not be used as main panel for group items layout.
<GroupStyle.Panel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Vertical"></WrapPanel>
</ItemsPanelTemplate>
</GroupStyle.Panel>

When you setup the GroupDescription as explained here, your items will be grouped into GroupItem collection and each group will be added as child to a Vertical StackPanel. The items inside a GroupItem will still use the WrapPanel you have defined as ItemsPanel, but since your WrapPanel's Orientation is set to Vertical and you are a descendant of a Vertical StackPanel (which gives Infinite vertical available space) the layout system does not wrap the items since it has all the space it needs to display the Items in a vertical manner.
Hope it made it clearer now and you can adapt your solution, maybe change the WrapPanel's Orientation to Horizontal.

below code (xaml) works in my case:
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>

Related

How to set WrapPanel itemsource to list?

I want to show in WrapPanel a list of images. How can I do that or maybe I shall use other control ?
You can absolutely use the WrapPanel to show a list of images, scrolling vertically or horizontally. To get the kind of panoramic tile effect like in People hub with your images, you could do something like this:
<controls:PanoramaItem Header="something" Orientation="Horizontal" Margin="0,-15,0,0" >
<ListBox Name="SomeList" Margin="0,0,-12,0" ItemsSource="{Binding SomeItemsList}" >
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<toolkit:WrapPanel x:Name="wrapPanel" Width="700" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="0,0,0,17">
<Image Height="200" Width="200" Margin="12,0,9,0" Source="{Binding ImageURL}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</controls:PanoramaItem>
Please note that a WrapPanel inside a ListBox does pick up the DataTemplate you define .. so you have complete liberty to bind any list to your WrapPanel.
Hope this helps!
Search for the same thing and came across this: Displaying a Collection of Items in a WrapPanel.
<ItemsControl ItemsSource="{Binding ActorList}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Image Source="{Binding Image}" Height="100"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
or you can use Xceed's SwitchPanel.
Yes definetly not the WrapPanel, it has not ItemsSource, it can't take a list.
Use the ListBox, and you can set the ItemsSource.
Edit

Wrap Panel is not wrapping DataItems

I have WrapPanel where I want the control inside of it to go horizontally and centered, but when I have a listbox or a ItemsControl those elements just go downwards.
<toolkit:WrapPanel>
<ItemsControl x:Name="AnswerListBox" ItemsSource="{Binding Answers}" ScrollViewer.VerticalScrollBarVisibility="Disabled" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<!-- those don't wrap horizontally and go downwards -->
<local:spriteToggleButton Text="{Binding text}" Selected="{Binding selected}" Sprites="{Binding Path=DataContext.UISprites, ElementName=questionField}" IsChecked="{Binding selected, Mode=TwoWay}" GroupName="{Binding Path=DataContext.QuestionTitle, ElementName=questionField}" ClickMode="Press" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</toolkit:WrapPanel>
I came across some similar issues and found out about ItemsPanel, so I tried that but it wrap but only to Content and didn't display the rest of the control inside of it.
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<toolkit:WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
I take it that ItemsPanel is telling the ItemsControl which control to wrap it with but then it seems to ignore the rest of my datatemplate.
Joseph,
Slightly shooting in the dark here; but this is how I have used the WrapPanel (not through the ItemControl).
<ListBox>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<toolkit:WrapPanel Width="700" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
....
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Essentially the Listbox's ItemsPanel tells it to use the WrapPanel and then you could have anything you need in the DataTemplate. Note that the width is important as it tells the WrapPanel where to start wrapping.
Does this help?

Can the groups of a grouped CollectionView be presented horizontally?

I'm implementing a ListBox whose ItemsPanel is a WrapPanel as per this answer, but there's a twist: my ItemsSource is a grouped CollectionView. With a GroupStyle applied to my ListBox, the wrapping shown in that question doesn't work: the groups are always displayed vertically.
Snooping on my app, here's why:
As you can see, the WrapPanel, defined as my ListBox's ItemsPanelTemplate, appears in the ItemsPresenter within each GroupItem; an implicit, vertically-oriented StackPanel (top item in the pink box) is created to contain the GroupItems themselves.
Is there a way to override this behavior, so the GroupItems are placed in a WrapPanel? Would I have to re-template the entire ListBox?
Update: To illustrate what I'm actually doing with my ListBox and the CollectionView grouping, let me post a little XAML:
<Grid>
<ListBox ItemsSource="{Binding}"
ScrollViewer.VerticalScrollBarVisibility="Disabled"
SelectionMode="Multiple"
ItemContainerStyle="{StaticResource itemStyle}">
<ListBox.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" FontWeight="Bold"/>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListBox.GroupStyle>
<ListBox.ItemTemplate>
<DataTemplate DataType="{x:Type WpfApplication1:Item}">
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Name}" FontSize="10"/>
<TextBlock Text="{Binding Amount, StringFormat={}{0:C}}" FontSize="10"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
</Grid>
The GroupStyle is at the heart of it: if you remove that, the GroupItems don't get rendered, and the WrapPanel (which you can see appearing beneath the GroupItem in the screenshot above) appears in place of (StackPanel) 98 in the screenshot.
This behavior only seems to occur if you have defined a HeaderTemplate in the GroupStyle.
It can be corrected by setting the GroupStyle.Panel property to contain a WrapPanel:
<ListBox.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" FontWeight="Bold"/>
</DataTemplate>
</GroupStyle.HeaderTemplate>
<GroupStyle.Panel>
<ItemsPanelTemplate>
<WrapPanel></WrapPanel>
</ItemsPanelTemplate>
</GroupStyle.Panel>
</GroupStyle>
</ListBox.GroupStyle>
It will look something like this:
You should be able to replace the group style from the items control (ListBox):
<ListBox.GroupStyle>
<Style />
<ListBox.GroupStyle/>
Or, you should also be able to create a DataTemplate based on the group item object:
<DataTemplate DataType="{x:Type GroupItem}">
<Panel />
</DataTemplate>

Separator in ItemsControl renders in different shades for each item

I have an ItemsControl presenting TextBlocks, with a Separator at the bottom of each item.
My problem is that each Separator is rendered in a slightly different shade of gray - it looks really dodgy:
Here is my XAML:
<ItemsControl ItemsSource="{Binding Path=Items}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel></StackPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding}" ></TextBlock>
<Separator></Separator>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I have also tried using a thin border instead of the Separator, with the same result.
How can I make each line identical?
Try SnapsToDevicePixels="True"
<ItemsControl ItemsSource="{Binding Path=Items}" SnapsToDevicePixels="True">
If this doesn't help you can also try with
UseLayoutRounding="True" (WPF 4)
RenderOptions.EdgeMode="Aliased" (Turn of anti-aliasing)

WPF: ListBox with WrapPanel, vertical scrolling problem

I have a UserControl (XAML below) that has a ListBox that I want to display images inside a WrapPanel, where images are displayed as many as will fit on one row and then wrap onto the next row etc. It works, except when the ListBox grows higher than the available space in the window, I'm not getting a vertical scrollbar, i.e. the contents get clipped. If I set a fixed height on the ListBox, the scrollbar appears and works as expected. How can I get this listbox to grow to the available space and then show a vertical scrollbar? This control is inside StackPanel inside a Grid in the main window. If I wrap the StackPanel inside a ScrollViewer, I get the scrollbar I'm after, but that's not really a good solution if I wanted to add some more controls to the UserControl above the ListBox (e.g. image size "zoom" etc) as I wouldn't want them to scroll with the images.
Thanks!! :)
<UserControl x:Class="GalleryAdmin.UI.GalleryView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ListBox Name="itemListBox" BorderThickness="0" ItemsSource="{Binding}" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Background="LightGray" Margin="5" >
<StackPanel Margin="5">
<Image Source="{Binding Path=LocalThumbPath}" Height="100" />
<TextBlock Text="{Binding Path=Name}" TextAlignment="Center"></TextBlock>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
I think you better go with override the ItemPanelTemplate:
<Grid>
<ListBox ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBoxItem>listbox item 1</ListBoxItem>
<ListBoxItem>listbox item 2</ListBoxItem>
<ListBoxItem>listbox item 3</ListBoxItem>
<ListBoxItem>listbox item 4</ListBoxItem>
<ListBoxItem>listbox item 5</ListBoxItem>
</ListBox>
Well, I finally stumbled upon the solution. I was adding my UserControl to a placeholder panel that looked like this:
<ScrollViewer Margin="20" >
<StackPanel Name="contentPanel"></StackPanel>
</ScrollViewer>
However, when I switched it to a Grid instead, things started to work the way I wanted:
<Grid Name="contentPanel" Margin="20" />
I think it has to do with the StackPanel not taking up all the vertical space by default, like the Grid is doing.
All I had to do was set the following, and the problem went away:
<ListBox ScrollViewer.HorizontalScrollBarVisibility="Disabled">
I was just looking through several questions about this issue, and although this is an old thread, this one gave me the answer, but just to clarify....
The layout GRID is the answer to most issues like this. To get the proper ListBox/WrapPanel operation to fill the available space, the following code does the trick:
<Grid Grid.Row="1" MaxHeight="105">
<ListBox ItemTemplate="{DynamicResource StoreGroupTemplate01}" ItemsSource="{Binding StoreGroupHeader}"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
</Grid>
I have this in another grid to place the list at the bottom of my screen (ie.. the Grid.Row="1") and you can adjust MaxHeight (or remove it) to control the visible area before the vertical scroll bar will show up.
Put your listbox inside of a ScrollViewer and then set the scrollviewer's VerticalScrollBarVisibility property to "Auto"
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
<ListBox Name="itemListBox" BorderThickness="0" ItemsSource="{Binding}" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Background="LightGray" Margin="5" >
<StackPanel Margin="5">
<Image Source="{Binding Path=LocalThumbPath}" Height="100" />
<TextBlock Text="{Binding Path=Name}" TextAlignment="Center"></TextBlock>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
</ScrollViewer>
HTH

Resources