Alternate row color for a wrappanel - wpf

I am trying to get an alternate row color effect on a Listbox / wrappanel. However since the orientation is Horizontal, The alternate columns are getting the alternate colors. I want the elements to be listed side ways and then wrapped. How can I set the alternate color on rows based on this.
<ListBox ItemsSource="{Binding MySource}" ItemContainerStyle="{StaticResource alternatingListItemStyle}" AlternationCount="2">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" MaxWidth="300"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding MyCaption}"/>
</DataTemplate>
</ListBox.ItemTemplate>

The possible reason for alternating color for columns is the 'MaxWidth'.
As the MaxWidth for WrapPanel is 300, it's possible to hold more than one item.
If you reduce the maxwidth, it may hold a single item.
Hope this helps.
(Can you explain why you are using a wrap panel in ItemsPanelTemplate?
I am not sure how you want the output to look like.)

Related

How to make the items in a WPF ListBox wrap horizontally and vertically

I want to show a list of thumbnails, and allow the user to choose one. A ListBox seemed an obvious choice, setting the template to include the thumbnail and description.
The following code does this correctly...
<ListBox Margin="5"
Name="BackgroundsLb">
<ListBox.ItemTemplate>
<DataTemplate>
<Border Margin="5"
BorderBrush="Black"
BorderThickness="1">
<StackPanel Margin="5">
<Image Source="{Binding Path=Data, Converter={StaticResource BytesToImageVC}}"
Width="150"
HorizontalAlignment="Center" />
<TextBlock Text="{Binding Path=Description}"
HorizontalAlignment="Center" />
</StackPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
However, this displays the thumbnails vertically, one per row, as is normal for a ListBox. Given that the thumbnails are only 150 pixels wide, I would like to show them in something more like a grid, but (ideally) in a way so that the number of columns adapts to the size of the window.
I tried replacing the ListBox with an ItemsControl, adding in the following...
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
...and it displayed exactly how I wanted it, but the ItemsControl does not allow selection, so is no use for my purpose.
Is there a way to achieve a flexible, selectable display that fills the horizontal space, and breaks onto a new row according to the size of the window?
Thanks
You can use an ItemsPanelTemplate in a ListBox just the same as you are using one in the ItemsControl. The difference I think you're seeing is that ListBox uses scroll bars by default rather than wrapping the content. Basically the content is allowed to grow forever, so you never get the wrap. Instead you get a scrollbar. The good news is you can disable this behavior. The following should give you a horizontal wrap, where new rows are created as needed.
<ListBox ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>

WPF itemscontrol child alignment

I have a WPF MVVM application with an itemscontrol. The number of horizontal child items is influenced by the itemscontrol width. There is only 1 thing i haven't solved. I'm trying to align the child elements in a way that there are always centered. I have made quick pictures in paint to demonstrate what i mean.
How it's now:
If the width further inceares then a forth item will be added horizontally. This function needs to stay.
How I would like to see it:
If there is enough room for a forth item then it needs to be added. I'm thinking that the answer could be a simple XAML property. Anybody an idea?
Put the ItemsControl in a Grid and set its HorizontalAlignment to Center:
<Grid>
<ItemsControl ItemsSource="{Binding Images}" HorizontalAlignment="Center">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Image Source="{Binding}" .../>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>

WPF: Create 8x8 TextBox table in codebehind

I need to create 8x8 TextBox table, each TextBox should be bound to element of double[,] array (i want to let user change matrix from ui).
What is the most elegant way to do this?
I would use an ItemsControl, and change the ItemPanel from the default StackPanel to a WrapPanel. Something like:
<ItemsControl>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
...
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Make use of a UniformGrid...
<UniformGrid>
<TextBox Text="{Binding SomeProperty}"/>
...
<TextBox Text="{Binding SomeProperty}"/>
</UniformGrid>
You may need to make use of an IValueConverter to deal with the way in which you are binding as well as setting the width and height to a fixed size to guarantee your 8x8 representation but the UniformGrid as a container should suffice to meet your goal of an 8x8 table.

WPF Listbox Wrapping

I have a listbox in which I use a ListBox.ItemsPanel - WrapPanel.
<ListBox ItemsSource="{Binding Path=Applets}" Margin="10,92,10,10" ScrollViewer.HorizontalScrollBarVisibility="Disabled" >
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Vertical" IsItemsHost="True">
</WrapPanel>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>...
I am trying to have the wrappanel have a behavior such that the items fill in to the right as the width is made wider and wrap as needed when the window is made narrower. I have played with it but the correct combination eludes me. Does anyone have a suggestion?
My next goal would be able to reorder/ sort the items and have the render update.
TIA
I am trying to have the wrappanel have a behavior such that the items fill in to the right as the width is made wider and wrap as needed when the window is made narrower. I have played with it but the correct combination eludes me. Does anyone have a suggestion?
The code you have is almost correct, just change the Orientation to Horizontal and it should work as you describe
My next goal would be able to reorder/ sort the items and have the render update.
You don't have to do anything special for that, it's the normal behavior of a ListBox. Just change the sort order (using ICollectionView.SortDescriptions), and the UI will reflect the changes
<ListBox Grid.Row="1" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBoxItem Name="lbiTmp3_1"><CheckBox>
<TextBlock TextWrapping="Wrap">
lkjfd gmlkdsfmlk gmdsgf kds lkjglfdjmlkg jfdsg dsgf lkhfdgs lkjds fg
</TextBlock></CheckBox>
</ListBoxItem>
<ListBoxItem Name="lbiTmp3_2">C0ucou</ListBoxItem>
<ListBoxItem Name="lbiTmp3_3">C0ucou</ListBoxItem>
</ListBox>

How to set Height of items in XAML so they always occupy the same proportion of available space in parent ItemsControl?

I have an ItemsControl with the following ItemTemplate:
<DataTemplate x:Key="myItemTemplate">
<TextBlock Height="???" Text="{Binding Path=Description}" />
</DataTemplate>
My question is, how do I set the Height of the TextBlock in the template so that it automatically assumes ItemsControl.Height div ItemsCount amount of vertical space?
When there's only one item, I'd like it to be the full height of container, when there're two, each should be half the size, and so on.
If possible, I'd prefer to do this completely in XAML to keep my ViewModel clean of UI logic.
You could use a UniformGrid as your ItemsPanelTemplate and bind the Rows property to the number of items in your ItemsControl, like so:
<ItemsControl>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Rows="{Binding Items.Count, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}}" IsItemsHost="True"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
I did not test this code, so you need to check it, but I think the idea is clear.
EDIT: As pointed out by John below, this code is even easier:
<ItemsControl>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="1" IsItemsHost="True"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
I'm going to try and remember this as an intellectual exercise as I'm very new to WPF. I have no doubt I'll be corrected in due course. I think that you can specify a constant proportion by appending a % sign to the Height value i.e. Height="50%". This is deceptive, as it will add up all the numeric values of the heights of elements inside the parent, and size each one as its proportion of this sum. For example, three textblocks each of height="50%" would each have a height (50/150)*height of datatemplate = 1/3.

Resources