Reputation: 361
I'm making a Windows 8.1 C# app where there is a list of color blocks in a line. The number of colors can change, and I want the color blocks to fill up the width of the list control. I have tried using ItemsControl like this:
<ItemsControl Name="testGrid" HorizontalAlignment="Left" Margin="12,100,0,0" Width="220" Background="Black">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Rectangle Fill="{Binding}" MinWidth="44" Height="44"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
I've tried GridView and ListView with item styles with HorizontalContentAlignment set to stretch as well. The main issue is that these are all vertical lists. I need a horizontal one.
If I try adding a StackPanel the stretched items stop working. Like this:
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
Here is an example image:
I'm using an item source bound to a List or Observable Collection. How would I go about achieving the effect in the image? Thanks
Upvotes: 2
Views: 1767
Reputation: 11
You can use UniformGrid with Rows="1"
<UniformGrid Rows="1">
<Border Margin="5,0" Background="Red" Height="20" ></Border>
<Border Margin="5,0" Background="Green" Height="20" ></Border>
<Border Margin="5,0" Background="Black" Height="20" ></Border>
<Border Margin="5,0" Background="Gray" Height="20" ></Border>
<Border Margin="5,0" Background="Orange" Height="20" ></Border>
</UniformGrid>
Upvotes: 0
Reputation: 6142
You'll need to calculate the available width and use that to evenly divide the space between all the items.
I've done what you need in a recent project, but it was done with a ListView
instead of an ItemsControl
.
All the calculation code is inside a custom control that inherits from Panel
public class SplitPanel : Panel
{
protected override Size MeasureOverride(Size availableSize)
{
// the final measure size is the available size for the width, and the maximum
// desired size of our children for the height
Size finalSize = new Size { Width = availableSize.Width };
if (this.Children.Count != 0)
availableSize.Width /= (double)this.Children.Count;
foreach (var current in this.Children)
{
current.Measure(availableSize);
Size desiredSize = current.DesiredSize;
finalSize.Height = Math.Max(finalSize.Height, desiredSize.Height);
}
// make sure it will works in design time mode
if (double.IsPositiveInfinity(finalSize.Height) || double.IsPositiveInfinity(finalSize.Width))
return Size.Empty;
return finalSize;
}
protected override Size ArrangeOverride(Size arrangeSize)
{
Rect finalRect = new Rect(new Point(), arrangeSize);
double width = arrangeSize.Width / this.Children.Count;
foreach (var child in this.Children)
{
finalRect.Height = Math.Max(arrangeSize.Height, child.DesiredSize.Height);
finalRect.Width = width;
child.Arrange(finalRect);
// move each child by the width increment
finalRect.X += width;
}
return arrangeSize;
}
}
When that is defined you can use it on a ListView
like this
<ListView x:Name="ImageList"
Margin="0,10,0,0"
Style="{StaticResource HorizontalListViewStyle}"
ItemContainerStyle="{StaticResource ImageBarListViewItemStyle}"
SelectedIndex="{Binding SelectedIndex, ElementName=MainPivot, Mode=TwoWay}"
Grid.Row="1">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<controls:SplitPanel />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
It will give you this result
For reference without the panel
Upvotes: 1
Reputation: 31724
I wouldn't use a Viewbox
since it's a can of worms - though it might work. I'd use an ItemsControl
with a custom panel used for its ItemsPanel
template. The UniformGrid
in my toolkit would almost work, but you'd need to somehow bind its Columns
(count) property to the number of elements in a list. It should be easy to modify though to not require a Columns
property if all you need is to equally divide the space. The SquareGrid
does it that way, but it expands in both directions.
Upvotes: 0
Reputation: 128061
If it's only about displaying filled rectangles, you might put the whole thing in a Viewbox
with fixed width and height and Stretch
set to Fill
:
<Viewbox Stretch="Fill" Width="220" Height="44">
<ItemsControl x:Name="testGrid">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Rectangle Fill="{Binding}" MinWidth="44" Height="44"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Viewbox>
Upvotes: 0