【问题标题】:How to overlay items in StackPanel or ListView?如何覆盖 StackPanel 或 ListView 中的项目?
【发布时间】:2017-01-30 23:08:33
【问题描述】:

我正在制作一款纸牌游戏,我想将玩家手中的纸牌显示为彼此半掩着。如何使用 ListView 或 StackPanel 做到这一点?这是我想如何显示玩家手牌的示例。

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

【问题讨论】:

  • 使用StackPanel 和负左或右margin
  • 当您说“ListView 项目的宽度不适合图像并且有一些间距”时,您是指 A 卡和 K 卡右侧的阴影吗?
  • 是的,我指的是影子
  • 您是否尝试在 ListViewItem 样式中设置 Background = Transparent?
  • 是的,不移除阴影。

标签: c# xaml listview uwp


【解决方案1】:

我会在列表中使用 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>

【讨论】:

  • 控制模板触发器的良好使用。 +1
  • 我第一次真正使用它们!我一开始是用普通触发器尝试的。这让我想做一些风格
猜你喜欢
  • 2015-01-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-28
  • 1970-01-01
  • 2022-06-22
  • 2023-04-08
  • 2011-09-27
相关资源
最近更新 更多