如何在StackPanel或ListView中叠加项目?

时间:2016-09-22 11:35:00

标签: c# xaml listview uwp

我正在制作一个纸牌游戏,我希望在玩家的手牌中显示半张牌。我怎么能用ListView或StackPanel做到这一点?以下是我想如何显示玩家手牌的示例。

Player Hand

<Grid Background="Green" >
        <Image x:Name="One" Width="100" Height="100" Margin="10,10,250,210"/>
        <Image x:Name="Two" Width="100" Height="100" Margin="10,10,210,210"/>
</Grid>

更新

我为ListView的ItemContainerStyle设置了边距并且它有效,但我有另一个问题。 ListView项目的宽度不适合图像,并且有一些间距。我该如何删除它。请参见XAML代码下方的图片。

<ListView Grid.Row="0" Grid.Column="0">
        <ListView.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel Orientation="Horizontal" />
            </ItemsPanelTemplate>
        </ListView.ItemsPanel>
        <ListView.ItemContainerStyle>
            <Style TargetType="ListViewItem">
                <Setter Property="Margin" Value="0, 0, -80, 0"></Setter>
                <Setter Property="Height" Value="100"></Setter>
                <Setter Property="Width" Value="100"></Setter>
            </Style>
        </ListView.ItemContainerStyle>
        <Image x:Name="One" MaxWidth="100" Height="100" />
        <Image x:Name="Two" MaxWidth="100" Height="100" />
    </ListView>

Player's Hand

1 个答案:

答案 0 :(得分:14)

我会在列表中使用Canvas,并将您的卡绘制到画布上,因为画布中绘制的内容不会被剪裁,而是通过画布ZIndex等进行管理。

根据所需的间距调整画布大小,并使内容过大。我还建议在使用列表框和使用模板时绑定到Items-source。

顺便说一下,我使用solidColorBrushes定义我的卡片,所以我可以绘制矩形,用你的图像源替换它。我已经在资源中定义了我的源代码,但实际上它将绑定到ObservableCollection(Say,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>

这给了我们这个:

enter image description here

现在,我们希望在画布中绘制所有列表项,所以让我们定义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中绘制的矩形宽度为60,因此这些矩形向右溢出。

enter image description here

我们已经覆盖了凌乱的标准选择和突出样式。但是,我们不知道突出显示和选择了什么,所以让我们重新添加一些功能。我们还可以添加阴影等内容:

<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>

现在我们有了这个:

enter image description here

注意,gif没有完全正确地进行选择。如果没有一些代码,我认为宽度问题很难修复。一种选择是制作一个IValueConverter,它根据卡片列表计算宽度,并将其绑定到Listview的Width属性。

修改

找到解决尺寸问题的方法!填充!当然。但是,我发现滚动查看器甚至剪辑它包含的画布(如果你考虑它就有意义)但是我们把所有的努力都隐藏了:

enter image description here

因此,您必须通过手动设置ControlTemplate来覆盖滚动查看器功能:

    <ListBox.Template>
        <ControlTemplate>
            <Border Padding="5,25,55,15" BorderBrush="Gray" BorderThickness="1">
                <ItemsPresenter />
            </Border>
        </ControlTemplate>
    </ListBox.Template>

所以现在padding占了最后一张牌的额外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>

enter image description here

它非常灵活,很容易添加&#34;坚持&#34;功能。动画将是下一个重要的步骤。

修改2

我现在正在玩。我不确定我是否喜欢跳到前面&#34;功能,如果他们只是偷看会更好。另外,将它们扇出(使用多重绑定):

enter image description here

使用以下模板:

<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>