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>
相关推荐
Macbethad5 小时前
工业设备维护程序技术方案
wpf
wniuniu_5 小时前
ceph入门
windows·ceph·eureka
Macbethad5 小时前
工业设备配方管理系统技术方案
wpf
吕了了5 小时前
41 制作自己的wim包+DIY微软官方ISO文件!
运维·windows·microsoft·电脑·系统
喵叔哟7 小时前
7.日志系统深入
wpf
私人珍藏库7 小时前
[吾爱大神原创工具] 照片视频整理工具 V1.0
windows·分类·工具·整理·照片·辅助
清风徐来Groot8 小时前
WPF布局之Grid
wpf
John_ToDebug8 小时前
从零开始:在 Windows 环境下拉取并编译 Chrome 源码全纪录
c++·chrome·windows
csdn_aspnet8 小时前
在Windows 11系统中关闭Chrome自动更新
chrome·windows