Hello all. I'm coding a custom panel representing the hand of cards. It's a panel that will stack the cards horizontally. If there isn't enough space, each card will overlap part of the card left of it. Minimum part should be always visible. I accomplished this and this is the code:
using System;
using System.Windows;
using System.Windows.Controls;
namespace Hand
{
public class Hand : Panel
{
//TODO Should be dependancy property
private const double MIN_PART = 0.5;
protected override Size MeasureOverride(Size availableSize)
{
Size desiredSize = new Size();
foreach (UIElement element in this.Children)
{
element.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
desiredSize.Width += element.DesiredSize.Width;
desiredSize.Height = Math.Max(desiredSize.Height, element.DesiredSize.Height);
}
return desiredSize;
}
protected override Size ArrangeOverride(Size finalSize)
{
//percentage of the visible part of the child.
double part = 1;
Double desiredWidth = 0;
//TODO Check how to get desired size because without looping
//this.DesiredSize is minimum of available size and size returned from MeasureOverride
foreach (UIElement element in this.Children)
{
desiredWidth += element.DesiredSize.Width;
}
if (desiredWidth > this.DesiredSize.Width)
{
//Every, but the last child should be overlapped
double lastChildWidth = this.Children[this.Children.Count - 1].DesiredSize.Width;
part = (this.DesiredSize.Width - lastChildWidth) / (desiredWidth - lastChildWidth);
part = Math.Max(part, MIN_PART);
}
double x = 0;
foreach (UIElement element in this.Children)
{
Rect rect = new Rect(x, 0, element.DesiredSize.Width, element.DesiredSize.Height);
element.Arrange(rect);
finalSize.Width = x + element.DesiredSize.Width;
x += element.DesiredSize.Width * part;
}
return finalSize;
}
}
}
I would like to add scrollbar when minimum part is reached, so that the user could still be able to view all the cards. I cannot accomplish this. I tried with the ScrollViewer like this:
<Window x:Class="TestScrollPanel.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:h="clr-namespace:Hand;assembly=Hand"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ScrollViewer HorizontalScrollBarVisibility="Auto">
<h:Hand>
<Button Width="100">One</Button>
<Button Width="150">Two</Button>
<Button Width="200">Three</Button>
</h:Hand>
</ScrollViewer>
</Grid>
</Window>
But this doesn't work because once horizontal scrollbar is visible, MeasureOveride and ArrangeOverride of Hand panel is never called and even if it would be called, Hand would get desired size to arrange all children without overlapping.
Could this be made with ScrollViewer at all and if not, another ideas would be appreciated. Thank you all for ypur help.
Jurica