HandyControl 3.5.x 版本 ListViewItem不显示问题

问题场景

HandyControl 版本升级过程中,由3.4.x 升级到3.5.x 过程中,遇到ListView 添加 ListViewItem 或者 自定义DataTemplate时,运行时ListView中无内容显示,查看可视化树,控件无子节点。

复现版本

原有版本为3.4.0,升级版本使用版本为3.5.0

xml 复制代码
<Project Sdk="Microsoft.NET.Sdk">
	<ItemGroup>
		<!--<PackageReference Include="HandyControl" Version="3.6.0-rc3" />
		<PackageReference Include="HandyControl" Version="3.4.0" />-->
		<PackageReference Include="HandyControl" Version="3.5.0" />
	</ItemGroup>
</Project>

实体数据

案例数据主要为两层,MainWindowViewModel 作为主窗口的VMCaseItemViewModel作为集合的VM

cs 复制代码
public class MainWindowViewModel
{
    public List<CaseItemViewModel> MyPropertys { get; set; }

    public MainWindowViewModel()
    {
        MyPropertys = new List<CaseItemViewModel>
        {
            new CaseItemViewModel { MyProperty = "1", MyProperty1 = "1", MyProperty2 = "1", MyProperty3 = "1" },
            new CaseItemViewModel { MyProperty = "2", MyProperty1 = "2", MyProperty2 = "2", MyProperty3 = "2" },
            new CaseItemViewModel { MyProperty = "3", MyProperty1 = "3", MyProperty2 = "3", MyProperty3 = "3" },
            new CaseItemViewModel { MyProperty = "4", MyProperty1 = "4", MyProperty2 = "4", MyProperty3 = "4" },
            new CaseItemViewModel { MyProperty = "5", MyProperty1 = "5", MyProperty2 = "5", MyProperty3 = "5" }
        };
    }
}

Xaml页面

xaml 复制代码
<ListView IsManipulationEnabled="False" ItemsSource="{Binding MyPropertys}">
    <!--<ListViewItem>1</ListViewItem>
    <ListViewItem>2</ListViewItem>
    <ListViewItem>3</ListViewItem>
    <ListViewItem>4</ListViewItem>
    <ListViewItem>5</ListViewItem>-->
    <ListView.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding MyProperty}"></TextBlock>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

运行效果

解决方案

幸运的是,该问题在3.6.x中已经被修复,主要针对3.5.x 使用用户,因为历史原因无法正常升级到3.6.x 版本,通过对比3.6.x 以及3.5.x 对应生成的Theme.xaml 代码和官方issues,找到如下变更。

代码比对

左侧为3.5.0,右侧为3.6.0-rc3版本反编译的变更差异。

官方变更,这个变更在2024年就已经修复。

解决思路

如果3.5.x 版本用户要进行本地修复,可以直接拷贝src/Shared/HandyControl_Shared/Themes/Styles/ListView.xamlListViewBaseStyle样式以及设置ListView 默认样式。

xaml 复制代码
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:hc="https://handyorg.github.io/handycontrol">
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/Theme.xaml"/>
    </ResourceDictionary.MergedDictionaries>

    <Style x:Key="ListViewBaseStyle" TargetType="ListView">
        <!--省略,文末提供完整内容-->
    </Style>
    <Style BasedOn="{StaticResource ListViewBaseStyle}" TargetType="ListView" />
</ResourceDictionary>

再次运行案例,效果如下,表明问题已经解决。

总结归纳

在定位并解决的过程中,也对ListView 本身有了更加深入的了解,对于ListView 父类为ListBox ,其样式也对ListView 可以生效,同理ItemControl 作为ListBox 的父类,对应的ItemsControl.HasItems 也能作为ListView 的属性触发使用。对应的笔者使用的ListView.xaml 样式代码完整内容如下:

xml 复制代码
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:hc="https://handyorg.github.io/handycontrol">
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/Theme.xaml"/>
    </ResourceDictionary.MergedDictionaries>

    <Style x:Key="ListViewBaseStyle" TargetType="ListView">
        <Setter Property="Background" Value="{DynamicResource SecondaryRegionBrush}" />
        <Setter Property="BorderBrush" Value="{DynamicResource BorderBrush}" />
        <Setter Property="BorderThickness" Value="1" />
        <Setter Property="Padding" Value="6" />
        <Setter Property="Foreground" Value="{DynamicResource PrimaryTextBrush}" />
        <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto" />
        <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto" />
        <Setter Property="ScrollViewer.CanContentScroll" Value="true" />
        <Setter Property="ScrollViewer.PanningMode" Value="Both" />
        <Setter Property="Stylus.IsFlicksEnabled" Value="False" />
        <Setter Property="VerticalContentAlignment" Value="Center" />
        <Setter Property="ItemContainerStyle" Value="{StaticResource ListViewItemBaseStyle}" />
        <Setter Property="hc:BorderElement.CornerRadius" Value="{StaticResource DefaultCornerRadius}" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ListView">
                    <ControlTemplate.Resources>
                        <Storyboard x:Key="Storyboard1">
                            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PART_VerticalScrollBar">
                                <EasingDoubleKeyFrame KeyTime="0:0:.2" Value=".8" />
                            </DoubleAnimationUsingKeyFrames>
                            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PART_HorizontalScrollBar">
                                <EasingDoubleKeyFrame KeyTime="0:0:.2" Value=".8" />
                            </DoubleAnimationUsingKeyFrames>
                        </Storyboard>
                        <Storyboard x:Key="Storyboard2">
                            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PART_VerticalScrollBar">
                                <EasingDoubleKeyFrame KeyTime="0:0:.2" Value="0" />
                            </DoubleAnimationUsingKeyFrames>
                            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PART_HorizontalScrollBar">
                                <EasingDoubleKeyFrame KeyTime="0:0:.2" Value="0" />
                            </DoubleAnimationUsingKeyFrames>
                        </Storyboard>
                    </ControlTemplate.Resources>
                    <Border CornerRadius="{Binding Path=(hc:BorderElement.CornerRadius),RelativeSource={RelativeSource TemplatedParent}}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="True">
                        <ScrollViewer Focusable="false">
                            <ScrollViewer.Template>
                                <ControlTemplate TargetType="ScrollViewer">
                                    <Grid>
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="*" />
                                            <ColumnDefinition Width="Auto" />
                                        </Grid.ColumnDefinitions>
                                        <Grid.RowDefinitions>
                                            <RowDefinition Height="Auto" />
                                            <RowDefinition Height="*" />
                                            <RowDefinition Height="Auto" />
                                        </Grid.RowDefinitions>
                                        <DockPanel Grid.ColumnSpan="2">
                                            <ScrollViewer DockPanel.Dock="Top" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden" Focusable="false">
                                                <GridViewHeaderRowPresenter AllowsColumnReorder="{Binding View.AllowsColumnReorder, RelativeSource={RelativeSource AncestorType=ListView}}" ColumnHeaderContainerStyle="{Binding View.ColumnHeaderContainerStyle, RelativeSource={RelativeSource AncestorType=ListView}}" ColumnHeaderToolTip="{Binding View.ColumnHeaderToolTip, RelativeSource={RelativeSource AncestorType=ListView}}" ColumnHeaderContextMenu="{Binding View.ColumnHeaderContextMenu, RelativeSource={RelativeSource AncestorType=ListView}}" ColumnHeaderTemplate="{Binding View.ColumnHeaderTemplate, RelativeSource={RelativeSource AncestorType=ListView}}" ColumnHeaderTemplateSelector="{Binding View.ColumnHeaderTemplateSelector, RelativeSource={RelativeSource AncestorType=ListView}}" Columns="{Binding View.Columns, RelativeSource={RelativeSource AncestorType=ListView}}" Margin="2,0" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                                            </ScrollViewer>
                                        </DockPanel>
                                        <hc:ToggleBlock Grid.Row="1" Grid.ColumnSpan="2" Grid.RowSpan="2" IsChecked="{Binding HasItems,RelativeSource={RelativeSource AncestorType=ListView},Mode=OneWay}" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch">
                                            <hc:ToggleBlock.CheckedContent>
                                                <ScrollContentPresenter x:Name="PART_ScrollContentPresenter" CanContentScroll="{TemplateBinding CanContentScroll}" />
                                            </hc:ToggleBlock.CheckedContent>
                                            <hc:ToggleBlock.UnCheckedContent>
                                                <hc:Empty Background="{DynamicResource RegionBrush}" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" />
                                            </hc:ToggleBlock.UnCheckedContent>
                                        </hc:ToggleBlock>
                                        <ScrollBar Style="{StaticResource ScrollBarBaseStyle}" Opacity="0" x:Name="PART_VerticalScrollBar" Grid.Column="1" Grid.Row="1" Maximum="{TemplateBinding ScrollableHeight}" Orientation="Vertical" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" Value="{Binding VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportHeight}" />
                                        <ScrollBar Style="{StaticResource ScrollBarBaseStyle}" Opacity="0" x:Name="PART_HorizontalScrollBar" Grid.Row="1" Maximum="{TemplateBinding ScrollableWidth}" Orientation="Horizontal" VerticalAlignment="Bottom" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" Value="{Binding HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportWidth}" />
                                    </Grid>
                                    <ControlTemplate.Triggers>
                                        <EventTrigger RoutedEvent="MouseEnter">
                                            <BeginStoryboard Storyboard="{StaticResource Storyboard1}" />
                                        </EventTrigger>
                                        <EventTrigger RoutedEvent="MouseLeave">
                                            <BeginStoryboard Storyboard="{StaticResource Storyboard2}" />
                                        </EventTrigger>
                                    </ControlTemplate.Triggers>
                                </ControlTemplate>
                            </ScrollViewer.Template>
                            <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                        </ScrollViewer>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Style.Triggers>
            <MultiTrigger>
                <MultiTrigger.Conditions>
                    <Condition Property="IsGrouping" Value="true" />
                    <Condition Property="VirtualizingPanel.IsVirtualizingWhenGrouping" Value="false" />
                </MultiTrigger.Conditions>
                <Setter Property="ScrollViewer.CanContentScroll" Value="false" />
            </MultiTrigger>
            <Trigger Property="ItemsControl.HasItems" Value="False">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="ListView">
                            <Border CornerRadius="{Binding Path=(hc:BorderElement.CornerRadius),RelativeSource={RelativeSource TemplatedParent}}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="True">
                                <hc:Empty Background="{DynamicResource RegionBrush}" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" />
                            </Border>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Trigger>
        </Style.Triggers>
    </Style>

    <Style BasedOn="{StaticResource ListViewBaseStyle}" TargetType="ListView" />
</ResourceDictionary>
相关推荐
Halo_tjn31 分钟前
Java Set集合知识点
java·开发语言·数据结构·windows·算法
YJlio38 分钟前
CSDN年度总结2025:技术逐梦不止,步履坚定向前
windows·学习·流程图
꧁༺℘₨风、凌๓༻꧂1 小时前
C# WPF 项目中集成 Pdf查看器
pdf·c#·wpf
十五年专注C++开发1 小时前
QProcess在Windows下不能正常启动exe的原因分析
开发语言·c++·windows·qprocess·createprocess
无限进步_1 小时前
C++ STL容器适配器深度解析:stack、queue与priority_queue
开发语言·c++·ide·windows·算法·github·visual studio
新手村-小钻风1 小时前
Windows 环境下安装 Docker 的详细教程(超详细图文)
windows·docker·容器
无限进步_2 小时前
C++ STL list容器深度解析与模拟实现
开发语言·数据结构·c++·windows·git·list·visual studio
驱动开发00713 小时前
Windows_Hello_Configuration_Analysis Windows Hello 配置过程分析 setup包分析
windows·驱动开发·云计算·计算机外设·usb重定向
weixin_4397062513 小时前
JAVA版日语50音训练(读音强化记忆)
windows
阿蒙Amon13 小时前
C#每日面试题-简述C#访问修饰符
windows·microsoft·c#