You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

UWP:ListViewItem指针悬停时显示内部Button(VisualStateManager实现)

问题描述

现有一个ListView,其列表项包含一个Visibility设为Collapsed的Button。需要实现:当指针悬停在包含该Button的ListViewItem上时,让Button变为可见。能否通过VisualStateManager实现?尝试了以下代码但未成功,是否可以仅用XAML无需C#实现?

<ListView x:Name="Items" Width="500" Height="700">
    <ListView.ItemTemplate>
        <DataTemplate>
            <Border>
                <VisualStateManager.VisualStateGroups>
                    <VisualStateGroup>
                        <VisualState x:Name="Normal"/>
                        <VisualState x:Name="PointerOver">
                            <Storyboard>
                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="OkButtom" Storyboard.TargetProperty="Visibility">
                                    <DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
                                </ObjectAnimationUsingKeyFrames>
                            </Storyboard>
                        </VisualState>
                    </VisualStateGroup>
                </VisualStateManager.VisualStateGroups>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="400"/>
                        <ColumnDefinition/>
                    </Grid.ColumnDefinitions>
                    <TextBlock Text="Some Text" Grid.Column="0"/>
                    <Button x:Name="OkButtom" Visibility="Collapsed" Content="OK" Grid.Column="1"/>
                </Grid>
            </Border>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>
解决方案

原代码不生效的核心原因:你把VisualStateGroups放在了DataTemplate内的Border上,但PointerOver状态属于ListViewItem容器,而非DataTemplate里的元素。以下提供两种纯XAML实现方式:

方式一:修改ListViewItem模板,用VisualStateManager控制

直接在ListViewItem的模板中定义状态切换逻辑,当Item进入悬停状态时,控制内部Button显示:

<ListView x:Name="Items" Width="500" Height="700">
    <ListView.ItemTemplate>
        <DataTemplate>
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="400"/>
                    <ColumnDefinition/>
                </Grid.ColumnDefinitions>
                <TextBlock Text="Some Text" Grid.Column="0"/>
                <Button x:Name="OkButtom" Visibility="Collapsed" Content="OK" Grid.Column="1"/>
            </Grid>
        </DataTemplate>
    </ListView.ItemTemplate>
    <ListView.ItemContainerStyle>
        <Style TargetType="ListViewItem">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="ListViewItem">
                        <Border x:Name="Root" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
                            <VisualStateManager.VisualStateGroups>
                                <VisualStateGroup x:Name="CommonStates">
                                    <VisualState x:Name="Normal"/>
                                    <VisualState x:Name="PointerOver">
                                        <Storyboard>
                                            <!-- 显示Button -->
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="OkButtom" Storyboard.TargetProperty="Visibility">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
                                            </ObjectAnimationUsingKeyFrames>
                                            <!-- 保留ListViewItem默认悬停背景效果 -->
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Root" Storyboard.TargetProperty="Background">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightListLowBrush}"/>
                                            </ObjectAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualState>
                                    <VisualState x:Name="Pressed">
                                        <!-- 保留默认点击状态样式 -->
                                        <Storyboard>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Root" Storyboard.TargetProperty="Background">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightListMediumBrush}"/>
                                            </ObjectAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualState>
                                </VisualStateGroup>
                            </VisualStateManager.VisualStateGroups>
                            <!-- 承载ItemTemplate内容 -->
                            <ContentPresenter x:Name="ContentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ListView.ItemContainerStyle>
</ListView>

方式二:绑定ListViewItem的IsPointerOver属性

这种方式更简洁,直接通过数据绑定控制Button可见性,无需修改Item模板:

<!-- 先在页面资源中添加布尔值转可见性转换器 -->
<Page.Resources>
    <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
</Page.Resources>

<ListView x:Name="Items" Width="500" Height="700">
    <ListView.ItemTemplate>
        <DataTemplate>
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="400"/>
                    <ColumnDefinition/>
                </Grid.ColumnDefinitions>
                <TextBlock Text="Some Text" Grid.Column="0"/>
                <Button x:Name="OkButtom" 
                        Content="OK" Grid.Column="1"
                        Visibility="{Binding IsPointerOver, RelativeSource={RelativeSource AncestorType=ListViewItem}, Converter={StaticResource BooleanToVisibilityConverter}}"/>
            </Grid>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

注:WPF默认自带BooleanToVisibilityConverter;UWP需手动实现或引用相关资源转换器。

内容的提问来源于stack exchange,提问作者Nazarii Krypiak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 00:25:28