我有一个ListView,它应该显示相当多的项目,包括"名称","缩略图"和"AnimationPosition"属性。每个项目类型的后台任务负责切换缩略图以对其进行动画处理。
现在不言而喻,这是一个相当繁重的操作,应该限制在尽可能少的项,例如虚拟化列表视图的可见/实现项。现在,我已经将 ListView 的数据上下文设置为 ObeservableCollection 实例,并将其绑定到其类型的属性。下面简要介绍了我的 XAML 代码。
<TabControl Grid.Row="0" Grid.Column="2">
<TabControl.Resources>
<Style x:Key="MediaItemStyle" TargetType="{x:Type ListViewItem}">
<Setter Property="Margin" Value="5,5,5,5"/>
<Setter Property="Padding" Value="0,0,0,0"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Grid HorizontalAlignment="Left" VerticalAlignment="Top" Height="Auto" >
<Border x:Name="border" BorderBrush="{x:Null}" BorderThickness="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" CornerRadius="2.5"/>
<StackPanel HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<ContentPresenter/>
</StackPanel>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="custom:MediaContainerListView">
<Setter Property="ItemsSource" Value="{Binding}"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled"/>
<Setter Property="ItemContainerStyle" Value="{StaticResource MediaItemStyle}"/>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<WrapPanel/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<DockPanel Width="256">
<Image DockPanel.Dock="Top" Height="144" StretchDirection="Both"
Stretch="Fill" Source="{Binding Thumbnail.Source,Mode=OneWay}"/>
<ProgressBar DockPanel.Dock="Top" Height="2"
Minimum="0" Maximum="{Binding Thumbnail.AnimationPosition.Length}"
Value="{Binding Thumbnail.AnimationPosition.Position}"
Visibility="{Binding Thumbnail.AnimationPosition.Visibility}"/>
<TextBlock DockPanel.Dock="Bottom" Height="40"
TextWrapping="Wrap" TextTrimming="CharacterEllipsis"
TextAlignment="Center" Text="{Binding Name}"/>
</DockPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</TabControl.Resources>
<TabItem Header="">
<custom:MediaContainerListView x:Name="MediaContainerView"></custom:MediaContainerListView>
</TabItem>
</TabControl>
基本上,我有两种方法可以启动/停止每个单独项目的动画。
public async void StartAnimation()
{
if( Count > 1 )
{
Task thumbnailAnimationTask = AnimationTask( AnimationCancellationToken.Token );
await thumbnailAnimationTask;
}
}
public void StopAnimation()
{
AnimationCancellationToken.Cancel();
}
我这里有两个问题。
- ListView 似乎实现了所有项目,而不仅仅是那些可见或实现范围内的项目。我怀疑我的 XAML 以某种方式杀死了虚拟化,并尝试了许多解决方案但没有成功。请注意,我需要我的列表视图可扩展到主窗口的尺寸,而不是固定的高度和宽度。
- 我需要在项目即将实现时调用 StartAnimation,在项目离开视图时调用 StopAnimation。
即使我的 ListView 没有正确虚拟化,如果我对 ObservableCollections 工作原理的理解是正确的,它只是由虚拟化管理的项的 UI 表示形式,而不是项本身,即从项的构造函数/析构函数调用 StartAnimation/StopAnimation 并没有多大帮助,因为它们在创建时会为每个项调用。
有没有一种巧妙的方法以某种方式通知每个项目它们即将实现或离开 ListView 视图?
更新:虚拟化无法正常工作的问题与WrapPanel有关,一旦我切换到VirtualizingStackPanel,它就开始正常工作。不幸的是,它与WrapPanel并不完全相同,并且由于.NET框架不提供VirtualizingWrapPanel,因此我选择使用此处的WrapPanel。它并不完美,但它可以完成工作。
你说是1/2
寻找对GetHashcode
的调用我认为它称之为GetHashcode只是为了找到它
偶然发现它在项目虚拟化时被调用
具有终止(不循环)的动画
我终于自己解决了这个问题。我知道它不必那么复杂,但事实并非如此。由于我已经创建了自己的 ListView 继承类,名为 MediaContainerListView,因此我可以重写它的一些虚拟方法。其中两个被证明正是我想要的。
protected override void PrepareContainerForItemOverride( DependencyObject element, object item )
在项目即将出现之前调用,并且
protected override void ClearContainerForItemOverride( DependencyObject element, Object item )
在项目即将消失之前调用。所以我在第一个中调用StartAnimation,在第二个中调用StopAnimation,它完美无缺!