Reputation: 3239
There's a StackPanel
<StackPanel x:Name="sp1" Orientation="Horizontal" BorderBrush="Black" BorderThickness="1" />
which is dynamically populated with rectangles:
var values = new[] { 30, 50, 20 };
foreach (int val in values)
{
sp1.Children.Add(new Rectangle
{
// Width = perecntage, not supported on Rectangle
VerticalAlignment = VerticalAlignment.Stretch,
Fill = new SolidColorBrush(colors.Pop()),
});
}
Width
has to be a proportion of the parent's width based on val
.
I've tried to set it via the SizeChanged
event, but this works only for enlarging. Shrinking the window doesn't bring the width back.
sp1.SizeChanged += (sender, args) =>
{
int i = 0;
foreach (var val in values)
{
var prop = (double)val / valuesSum;
var r = (Rectangle)sp1.Children[i++];
r.Width = (int)(prop * args.NewSize.Width);
}
}
The only objective is to have a bar that is proportionally divided and stretched. Any idea?
Upvotes: 1
Views: 529
Reputation: 3239
This can be achieved by calling child.Arrange()
, which lets you set X
.
The child has to have Width
unset, otherwise it takes precedence.
sp1.SizeChanged += (sender, e) =>
{
var childRect = new Rect(0, 0, 0, e.NewSize.Height);
for (int i = 0; i < values.Length; i++)
{
var childWidth = (double)values[i] / valuesSum * e.NewSize.Width;
childRect.Width = childWidth;
so1.Children[i].Arrange(childRect);
childRect.X += childWidth;
}
}
I tried RelativePanel
and StackPanel
and both worked the same.
This can also be done in a class derived from Panel
. The code is the same, but it's called from overridden ArrangeOverride()
.
Upvotes: 0
Reputation: 5765
It isn't entirely clear why you want to use a StackPanel
for this. A StackPanel grows as it's contents get larger, the individual controls are 'stacked' to fit into the space available to the StackPanel. That doesn't match your requirements for "a bar that is proportionally divided and stretched".
If you use something like a Grid
, you can define the columns and rows to be proportionally spaced. For example, a Grid with two columns whose widths are defined as 2*
and 3*
those columns will be two-fifths of the width of the Grid, and three-fifths (fifths because 2+3=5). Needless to say, you can have as many columns as you like, and define the relative sizing as you require, possibly using 30*,50*,20* from information in the question. Or if you take the stars away, the values become literal values rather than relative values.
If you just want something to evenly space things out, try a UniformGrid
. You can limit the number of columns or rows.
If you have some complex need which is not covered by anything else, you can write a custom container control.
Upvotes: 1