Reputation: 478
Yesterday I asked how to get an ItemsControl to have its children equally distributed across the available space; and after happily reading the answer, I wrote (well actually kind of copied and adjusted it) my own "stretchpanel", which does exactly what i want. However my children are supposed to have a border on their right side, which works, as long as the child is bigger than its content. As soon as it gets smaller the border disappears and i can't tell why (and thus, not fix it). Below you can find a simplified version of my view and of the overriden methods from my stretchpanel, using this sample as basis. Thanks a lot in advance.
<Grid Background="Red" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<ItemsControl x:Name="HorizontalListBox" Background="Blue" HorizontalAlignment="Left" HorizontalContentAlignment="Left" >
<ItemsControl.Items>
<System:String>Test</System:String>
<System:String>Test</System:String>
<System:String>This demonstrates the problem exceptionally well</System:String>
<System:String>Test</System:String>
<System:String>Test</System:String>
</ItemsControl.Items>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Controls:StretchPanel Orientation="Horizontal" HorizontalAlignment="Stretch"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Background="Yellow" HorizontalAlignment="Stretch">
<TextBlock Text="{Binding}" HorizontalAlignment="Stretch"/>
<Border BorderBrush="Black" BorderThickness="0,0,1,0"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
protected override Size MeasureOverride(Size availableSize)
{
var size = new Size();
SetSide(ref size, GetSide(availableSize));
foreach (UIElement child in Children)
{
child.Measure(availableSize);
SetOtherSide(ref size, Math.Max(GetOtherSide(size), GetOtherSide(child.DesiredSize)));
}
_measureSize = size;
return size;
}
protected override Size ArrangeOverride(Size finalSize)
{
double offset = 0;
var Side = GetSide(_measureSize) / Children.Count;
var Rest = GetSide(_measureSize) % Children.Count;
foreach (UIElement child in Children)
{
double side = Math.Floor(GetSide(_measureSize) / Children.Count);
if (Rest > 0)
{
side++;
Rest--;
}
var final = new Size();
SetSide(ref final, side);
SetOtherSide(ref final, GetOtherSide(finalSize));
child.Arrange(new Rect(GetOffsetPoint(offset), final));
offset += side;
}
return finalSize;
}
Upvotes: 1
Views: 89
Reputation: 128147
It will work if you write your StretchPanel like this, which measure its child elements with zero width and height:
public class StretchPanel : Panel
{
protected override Size MeasureOverride(Size availableSize)
{
foreach (UIElement element in Children)
{
element.Measure(new Size());
}
return new Size();
}
protected override Size ArrangeOverride(Size finalSize)
{
for (int i = 0; i < Children.Count; i++)
{
int x1 = (int)(finalSize.Width / Children.Count * i);
int x2 = (int)(finalSize.Width / Children.Count * (i + 1));
Children[i].Arrange(new Rect(x1, 0, x2 - x1, finalSize.Height));
}
return finalSize;
}
}
and then set HorizontalAlignment="Stretch"
(or don't set it at all, since that is the default value) on the ItemsControl.
Upvotes: 1