2015-06-21 3 views
0

У меня есть ListView, который должен отображать довольно большое количество элементов, состоящих из «Name», «Thumbnail» и «AnimationPosition». Фоновая задача в типе каждого элемента отвечает за переключение эскизов, чтобы оживить их.ListView элементов из ObservableCollection, которые должны быть подготовлены к реализации

Теперь само собой разумеется, что это довольно тяжелая операция и должна ограничиваться как можно меньшим количеством элементов, например. для видимых/реализующих элементов виртуализированного ListView. Теперь я уже установил DataContext моего 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(); 
     } 

У меня есть две проблемы.

  1. ListView, похоже, реализует все элементы, а не только видимые или внутри диапазона реализации. Я подозреваю, что мой XAML как-то убивает виртуализацию и пробовал много решений без успеха. Имейте в виду, что мне нужно, чтобы мой ListView был масштабируемым для размеров MainWindow и не имел фиксированной высоты и ширины.
  2. Мне нужно вызвать StartAnimation, когда элемент будет реализован, и StopAnimation, когда он покинул представление.

Хотя мой ListView не правильно Виртуализованная, если мое понимание того, как ObservableCollections работа является правильным, это только представление UI из элементов, которые управляются с помощью виртуализации, а не предметы сами по себе, т.е. вызов StartAnimation/StopAnimation от конструктора/деструктора элементов не очень помогают, так как они вызываются для каждого элемента во время создания в любом случае.

Есть ли опрятный способ информировать каждый элемент, который они собираются реализовать, или оставить представление ListView?

Update: Вопрос виртуализация не работает должным образом было связано с WrapPanel и когда я переключился на VirtualizingStackPanel он начал работать правильно. К сожалению, это не совсем то же самое, что WrapPanel, и так как .NET framework не предлагает VirtualizingWrapPanel, я решил использовать его с here. Это не идеально, но это делает работу.

+0

Call StartAnimation из GetHashCode. Что касается Stop, я не знаю. – Paparazzi

+0

Спасибо @Blam, он решает половину проблемы. Давайте посмотрим, сможет ли кто-нибудь еще найти решение, которое идет полным ходом. –

ответ

0

Я, наконец, решил проблему самостоятельно. Я знал, что это не должно быть так сложно, и это действительно так. Поскольку я уже создал свой собственный наследуемый класс ListView, называемый MediaContainerListView, я мог бы переопределить некоторые из его виртуальных методов. Двое из них оказались такими, какие я хотел.

protected override void PrepareContainerForItemOverride(DependencyObject element, object item) 

, которая вызывается непосредственно перед деталь вот-вот появится, и

protected override void ClearContainerForItemOverride(DependencyObject element, Object item) 

, которая вызывается непосредственно перед деталь собирается исчезнуть. Поэтому я называю StartAnimation в первом и StopAnimation во втором, и он работает безупречно!

0

Вы сказали, что 1/2

Ищет вызов GetHashCode
Я думаю, что она называет это GetHashCode просто найти его
Я случайно обнаружил, что это называется, когда элемент виртуализируется

Имейте анимацию, которая заканчивается (не работает)

+0

Ну, проблема в том, что мне нужна анимация, чтобы продолжать играть, пока объект в поле зрения. О GetHashCode, вы правы, он называется (не один раз, а несколько раз) перед или во время реализации элемента. Это, по-видимому, простая вещь, которую нужно делать, не может себе представить, почему для этого не должно существовать простое решение. –

+0

Я также обнаружил, что моя проблема с виртуализацией не работает правильно из-за WrapPanel, который я использую. До сих пор, похоже, мой единственный шанс - использовать стороннюю или открытую WrapPanel, которая поддерживает виртуализацию или реализовать мою собственную, и в этом случае я также могу решить вторую проблему. –

Смежные вопросы