0

我有一个 ListView,它应该显示由“名称”、“缩略图”和“AnimationPosition”属性组成的相当多的项目。每个项目类型中的后台任务负责切换缩略图以对其进行动画处理。

现在不言而喻,这是一个相当繁重的操作,应该限制为尽可能少的项目,例如虚拟化 ListView 的可见/实现项目。现在我已经将 ListView 的 DataContext 设置为 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();
      }

我这里有两个问题。

  1. ListView 似乎实现了所有项目,而不仅仅是那些可见或在实现范围内的项目。我怀疑我的 XAML 以某种方式杀死了虚拟化,并且尝试了许多解决方案但没有成功。请注意,我需要我的 ListView 可以扩展到 MainWindow 的尺寸,而不是固定的高度和宽度。
  2. 当一个项目即将被实现时,我需要调用 StartAnimation,当它离开视图时,我需要调用 StopAnimation。

即使我的 ListView 没有正确虚拟化,如果我对 ObservableCollections 工作原理的理解是正确的,那么它只是由虚拟化管理的项目的 UI 表示,而不是项目本身,即从 Constructor/Destructor 调用 StartAnimation/StopAnimation这些项目并没有多大帮助,因为无论如何在创建时它们都被要求用于每个项目。

是否有一种巧妙的方法可以以某种方式通知每个项目它们即将实现或离开 ListView 视图?

更新: 虚拟化无法正常工作的问题与WrapPanel有关,一旦我切换到VirtualizingStackPanel,它就开始正常工作。不幸的是,它与WrapPanel并不完全相同,并且由于 .NET 框架不提供VirtualizingWrapPanel,因此我选择使用此处的那个。它并不完美,但可以完成工作。

4

2 回答 2

0

你说是1/2

寻找对 GetHashcode 的调用
我认为它调用它只是为了找到它
偶然我发现它在项目被虚拟化时被调用

有一个终止的动画(不循环)

于 2015-06-21T17:52:17.603 回答
0

我终于自己解决了这个问题。我知道它不必那么复杂,而且真的不是。由于我已经创建了自己的 ListView 继承类,称为 MediaContainerListView,因此我可以覆盖它的一些虚拟方法。其中两个证明正是我想要的。

protected override void PrepareContainerForItemOverride( DependencyObject element, object item )

在项目即将出现之前调用它,并且

protected override void ClearContainerForItemOverride( DependencyObject element, Object item )

在项目即将消失之前调用它。所以我在第一个中调用 StartAnimation,在第二个中调用 StopAnimation,它完美地工作!

于 2015-08-25T21:50:57.873 回答