I am currently developing a card game in WPF, where the user can drag cards from their hand. A dragged card should be always on top when overlapping other controls. Simplifying the problem, lets take a Grid control with 2 children. When comes to overlapping the child (and its contents), which was added to the Grid last, will be the top element. But for some reason when the child’s Content has bigger space demand than actually available for itself, the child and all of its content becomes bottom layer compared to others’ layer level.
As you can see on the attached video the player’s hand Grid is indicated with aqua colour. When there is NOT enough space for the cards, overlapping the dark green area with the dragged card fails. When the window is resized and there is enough space for all the cards, the overlapping works fine.
Here is the code:
<Window x:Class="CardMovementLayerIssue.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:CardMovementLayerIssue"
x:Name="GameControlCodeBehind"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid Background="#FF008000"
x:Name="MainGridPanel">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid Background="#FF005000">
</Grid>
<Grid Grid.Row="1"
x:Name="BottomSection">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="200"/>
</Grid.ColumnDefinitions>
<Grid Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid x:Name="LocalPlayerHand"
Background="Aqua"
MinHeight="{Binding CurrentCardHeight, ElementName=GameControlCodeBehind}"
Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
</Grid>
</Grid>
</Grid>
</Grid>
And the code behind:
private void Card_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
_originalPoint = e.GetPosition(MainGridPanel);
Image card = (Image)sender;
_draggedCard = card;
}
private void MainGridPanel_MouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed && _draggedCard != null)
{
Point currentPosition = e.GetPosition(MainGridPanel);
TranslateTransform translateTransform = new TranslateTransform(currentPosition.X - _originalPoint.X, currentPosition.Y - _originalPoint.Y);
TransformGroup transformGroup = new TransformGroup();
transformGroup.Children.Add(translateTransform);
_draggedCard.RenderTransform = transformGroup;
}
}
private void Card_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (_draggedCard != null)
{
_draggedCard = null;
}
}
I tried to play with the ZIndex
, but it seems it does not help me with this problem.
My question would be how to force a control to be always on top when comes to overlapping? Or how to achive the desired behaviour?
Thanks in advance!