我如何正确实现样式触发器以在 ListView 完成填充时触发?
How do i correctly implement a style trigger to fire when a ListView finishes populating?
我想设置 ListView
的样式,以便在填充后外观会发生变化。我发现 ListView
中有一个叫做 ItemContainerGenerator
的东西,它包含一个 Status
属性,完成后将被设置为 ContainersGenerated
(我想想 ).
所以为了实现这个目标,我认为最好的方法是定义一个样式数据触发器来触发 属性。
但它不起作用(当然)。我看到的是输出中的以下错误 -
System.Windows.Data Error: 17 : Cannot get 'Status' value (type 'GeneratorStatus') from '' (type 'ListView'). BindingExpression:Path=(ItemContainerGenerator.Status); DataItem='ListView' (Name=''); target element is 'ListView' (Name=''); target property is 'NoTarget' (type 'Object') TargetException:'System.Reflection.TargetException: Object does not match target type.
at System.Reflection.RuntimeMethodInfo.CheckConsistency(Object target)
at System.Reflection.RuntimeMethodInfo.InvokeArgumentsCheck(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.RuntimePropertyInfo.GetValue(Object obj, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture)
at System.Reflection.RuntimePropertyInfo.GetValue(Object obj, Object[] index)
at MS.Internal.Data.PropertyPathWorker.GetValue(Object item, Int32 level)
at MS.Internal.Data.PropertyPathWorker.RawValue(Int32 k)'
在提问时符合 Minimal, Complete and Verifiable Example 要求 -
- 在 Visual Studio 中创建一个名为 'MCVE' 的新项目。
- 将以下代码复制并粘贴到 MainWindow.xaml 代码上。
运行 程序。获取数据错误。默默流泪
<Window
x:Class="MCVE.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:MCVE"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<ListView>
<ListView.Style>
<Style TargetType="{x:Type ListView}">
<Style.Triggers>
<DataTrigger
Binding="{Binding
(ItemContainerGenerator.Status),
RelativeSource={RelativeSource Self}}"
Value="{x:Static GeneratorStatus.ContainersGenerated}">
<!-- This is where I'd put my setters - IF THE TRIGGER WORKED!!! -->
<Setter Property="Background" Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
</ListView.Style>
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Margin" Value="0" />
<Setter Property="Padding" Value="0" />
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid HorizontalAlignment="Center" Rows="1" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListViewItem>Foo</ListViewItem>
<ListViewItem>Bar</ListViewItem>
<ListViewItem>Baz</ListViewItem>
</ListView>
</Window>
(不幸的是,因为它都在 XAML 中,我必须将整个代码块包装在 ` 中才能显示)
那么我怎样才能正确创建一个数据触发器,它会在 ListView
完成填充时触发?
删除 ItemContainerGenerator.Status 两边的括号。为我工作。顺便说一句,如果您正在使用回收,您将在滚动时不断切换状态。如果您的列表需要很长时间才能填充,听起来您应该使用回收和虚拟化。对于 "normal" 个项目,用户甚至不会看到未完成的状态,因为它会立即发生。
我想设置 ListView
的样式,以便在填充后外观会发生变化。我发现 ListView
中有一个叫做 ItemContainerGenerator
的东西,它包含一个 Status
属性,完成后将被设置为 ContainersGenerated
(我想想 ).
所以为了实现这个目标,我认为最好的方法是定义一个样式数据触发器来触发 属性。
但它不起作用(当然)。我看到的是输出中的以下错误 -
System.Windows.Data Error: 17 : Cannot get 'Status' value (type 'GeneratorStatus') from '' (type 'ListView'). BindingExpression:Path=(ItemContainerGenerator.Status); DataItem='ListView' (Name=''); target element is 'ListView' (Name=''); target property is 'NoTarget' (type 'Object') TargetException:'System.Reflection.TargetException: Object does not match target type.
at System.Reflection.RuntimeMethodInfo.CheckConsistency(Object target)
at System.Reflection.RuntimeMethodInfo.InvokeArgumentsCheck(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.RuntimePropertyInfo.GetValue(Object obj, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture)
at System.Reflection.RuntimePropertyInfo.GetValue(Object obj, Object[] index)
at MS.Internal.Data.PropertyPathWorker.GetValue(Object item, Int32 level)
at MS.Internal.Data.PropertyPathWorker.RawValue(Int32 k)'
在提问时符合 Minimal, Complete and Verifiable Example 要求 -
- 在 Visual Studio 中创建一个名为 'MCVE' 的新项目。
- 将以下代码复制并粘贴到 MainWindow.xaml 代码上。
运行 程序。获取数据错误。默默流泪
<Window x:Class="MCVE.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:MCVE" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <ListView> <ListView.Style> <Style TargetType="{x:Type ListView}"> <Style.Triggers> <DataTrigger Binding="{Binding (ItemContainerGenerator.Status), RelativeSource={RelativeSource Self}}" Value="{x:Static GeneratorStatus.ContainersGenerated}"> <!-- This is where I'd put my setters - IF THE TRIGGER WORKED!!! --> <Setter Property="Background" Value="Red" /> </DataTrigger> </Style.Triggers> </Style> </ListView.Style> <ListView.ItemContainerStyle> <Style TargetType="{x:Type ListViewItem}"> <Setter Property="BorderThickness" Value="0" /> <Setter Property="Margin" Value="0" /> <Setter Property="Padding" Value="0" /> </Style> </ListView.ItemContainerStyle> <ListView.ItemsPanel> <ItemsPanelTemplate> <UniformGrid HorizontalAlignment="Center" Rows="1" /> </ItemsPanelTemplate> </ListView.ItemsPanel> <ListViewItem>Foo</ListViewItem> <ListViewItem>Bar</ListViewItem> <ListViewItem>Baz</ListViewItem> </ListView> </Window>
(不幸的是,因为它都在 XAML 中,我必须将整个代码块包装在 ` 中才能显示)
那么我怎样才能正确创建一个数据触发器,它会在 ListView
完成填充时触发?
删除 ItemContainerGenerator.Status 两边的括号。为我工作。顺便说一句,如果您正在使用回收,您将在滚动时不断切换状态。如果您的列表需要很长时间才能填充,听起来您应该使用回收和虚拟化。对于 "normal" 个项目,用户甚至不会看到未完成的状态,因为它会立即发生。