我会在列表中使用 Canvas,并将您的卡片绘制到画布上,因为在画布中绘制的内容不会被剪裁,而是通过画布 ZIndex 等进行管理。
根据您想要的间距调整画布大小,并加大内容的大小。我还建议在使用列表框和模板时绑定到 Items-source。
顺便说一句,我正在使用solidColorBrushes 定义我的卡片,这样我就可以绘制矩形,将其替换为您的图像源。我已经在资源中定义了我的来源,但实际上它会绑定到 ObservableCollection(比如,PlayersCurrentHand 或其他东西):
<UserControl.Resources>
<x:Array Type="{x:Type SolidColorBrush}" x:Key="Cards">
<SolidColorBrush Color="Blue"/>
<SolidColorBrush Color="Red"/>
<SolidColorBrush Color="White"/>
<SolidColorBrush Color="White"/>
<SolidColorBrush Color="White"/>
<SolidColorBrush Color="White"/>
</x:Array>
</UserControl.Resources>
现在,我假设您使用 ListBox 是因为您想支持选择?如果是这样,WPF 突出显示列表框项的方式将与这种重叠混淆,因此我们需要替换它。如果您不想选择,只需使用 itemsControl,您就可以跳过所有选择内容。
这是我们的基本列表框:
<ListView ItemsSource="{StaticResource Cards}" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="112,98,-325,-25" Width="513" Height="227">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" IsItemsHost="True" VerticalAlignment="Top"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Black" BorderThickness="1">
<Rectangle Fill="{Binding}" Width="60" Height="100"/>
</Border>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
这给了我们这个:
现在,我们想要在画布中绘制所有列表项,所以让我们定义我们的 ItemContainerStyle:
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<StackPanel>
<Canvas Width="15" Height="100">
<ContentPresenter />
</Canvas>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
看看我们是如何将画布宽度设置为 15 的?这定义了我们卡片的间距。所有的画布都以 15 的间隔堆叠。但是,我们在 DateTemplate 中绘制的 Rectangles 的宽度是 60,所以它们会溢出到右侧。
我们已经覆盖了凌乱的标准选择和突出显示样式。但是不,我们不知道突出显示和选择了什么,所以让我们重新添加一些功能。我们还可以添加阴影等内容:
<ControlTemplate TargetType="{x:Type ListViewItem}">
<StackPanel>
<Canvas Width="15" Height="100">
<Rectangle x:Name="Highlight" Width="60" Height="5" Canvas.Top="105"/>
<Rectangle Fill="#50000000" Width="60" Height="100" Margin="5,0,-5,0"/>
<ContentPresenter />
</Canvas>
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Highlight" Property="Fill" Value="Yellow"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Panel.ZIndex" Value="99"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
所以现在我们有了这个:
请注意,gif 没有完全正确地呈现选择。我认为如果没有一些代码,宽度问题将很难解决。一种选择是创建一个 IValueConverter,计算给定卡片列表的宽度,并将其绑定到 Listview 的 Width 属性。
编辑
找到了解决尺寸问题的方法!填充!当然。但是,我发现滚动查看器甚至会剪辑它包含的画布(如果您考虑一下,这是有道理的),但隐藏了我们所有的努力:
因此您必须通过手动设置 ControlTemplate 来覆盖滚动查看器功能:
<ListBox.Template>
<ControlTemplate>
<Border Padding="5,25,55,15" BorderBrush="Gray" BorderThickness="1">
<ItemsPresenter />
</Border>
</ControlTemplate>
</ListBox.Template>
所以现在填充占最后一张卡的额外 50。
总代码,还有一些视觉上的调整:
<ListView ItemsSource="{StaticResource Cards}" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="20" BorderBrush="Black">
<ListBox.Template>
<ControlTemplate>
<Border Padding="5,25,55,15" BorderBrush="Gray" BorderThickness="1">
<ItemsPresenter />
</Border>
</ControlTemplate>
</ListBox.Template>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" IsItemsHost="True" ClipToBounds="False" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<StackPanel>
<Canvas Width="15" Height="100">
<Rectangle x:Name="Highlight" Width="60" Height="5" Canvas.Top="105"/>
<ContentPresenter x:Name="CardPresenter"/>
</Canvas>
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Panel.ZIndex" Value="99"/>
<Setter TargetName="CardPresenter" Property="Canvas.Top" Value="-5"/>
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Highlight" Property="Fill" Value="Yellow"/>
<Setter TargetName="CardPresenter" Property="Canvas.Top" Value="-20"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Border Background="#60000000" BorderThickness="0" CornerRadius="5" Height="100" Margin="5,0,-5,0"/>
<Border BorderBrush="Black" BorderThickness="1" CornerRadius="5" Background="{Binding}" Width="60" Height="100"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
它非常灵活,很容易添加“伸出”功能。动画将是下一大步。
编辑 2
我现在只是在玩。我不确定我是否喜欢“跳到前面”功能,如果他们只是偷看会更好。另外,将它们散开(使用多重绑定):
使用以下模板:
<ControlTemplate TargetType="{x:Type ListViewItem}">
<StackPanel>
<Canvas Width="15" Height="100">
<Rectangle x:Name="Highlight" Width="60" Height="5" Canvas.Top="105"/>
<ContentPresenter x:Name="CardPresenter">
<ContentPresenter.RenderTransform>
<TransformGroup>
<TranslateTransform x:Name="TranslateTransformHighlight"/>
<RotateTransform x:Name="RotateTransformHighlight" CenterY="100"/>
<TranslateTransform x:Name="TranslateTransformSelect"/>
</TransformGroup>
</ContentPresenter.RenderTransform>
</ContentPresenter>
</Canvas>
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True" >
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="TranslateTransformHighlight" Duration="0:0:0.200" To="-5" Storyboard.TargetProperty="Y" />
<DoubleAnimation Storyboard.TargetName="RotateTransformHighlight" Duration="0:0:0.200" To="-5" Storyboard.TargetProperty="Angle" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="TranslateTransformHighlight" Duration="0:0:0.200" To="0" Storyboard.TargetProperty="Y" />
<DoubleAnimation Storyboard.TargetName="RotateTransformHighlight" Duration="0:0:0.200" To="0" Storyboard.TargetProperty="Angle" />
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Highlight" Property="Fill" Value="Yellow"/>
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="TranslateTransformSelect" Duration="0:0:0.200" To="-15" Storyboard.TargetProperty="Y" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="TranslateTransformSelect" Duration="0:0:0.200" To="0" Storyboard.TargetProperty="Y" />
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>