2010-01-05 5 views
7

Wie kann ich das Flackern der Checkboxen in einer WPF ListBox oder ListView vermeiden? Es kann mit dem folgenden Code wiedergegeben werden, indem Sie auf die Schaltfläche Aktualisieren klicken oder indem Sie die Listbox scrollen. Wenn IsChecked falsch ist, flackert es nicht.WPF: Wie kann ich das Flackern der Checkboxen in einer ListBox oder einem ListView vermeiden?

Window1.xaml:

<Window x:Class="WpfApplication6.Window1" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="Window1" Height="300" Width="300"> 
    <Grid> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition/> 
      <ColumnDefinition/> 
     </Grid.ColumnDefinitions> 
     <ListBox Name="listBox"> 
      <ListBox.ItemTemplate> 
       <DataTemplate> 
        <StackPanel Orientation="Horizontal"> 
         <CheckBox IsChecked="True" 
            VerticalAlignment="Center"/> 
         <Label Padding="3" 
           Content="{Binding}"/> 
        </StackPanel> 
       </DataTemplate> 
      </ListBox.ItemTemplate> 
     </ListBox> 
     <Button Content="Refresh" 
       Grid.Column="1" 
       VerticalAlignment="Top" 
       Click="Button_Click"/> 
    </Grid> 
</Window> 

Window1.xaml.cs:

using System.Windows; 

namespace WpfApplication6 
{ 
    partial class Window1 : Window 
    { 
     public Window1() 
     { 
      InitializeComponent(); 
      Button_Click(null, null); 
     } 

     void Button_Click(object sender, RoutedEventArgs e) 
     { 
      var items = new int[10000]; 
      for (int i = 0; i < items.Length; i++) 
       items[i] = i + 1; 
      listBox.ItemsSource = items; 
     } 
    } 
} 

Antwort

2

Wollen Sie Checkbox aktiviert werden? Ich denke, Sie müssen die Animation ändern, wenn Sie das Kontrollkästchen aktivieren.

es auf Windows XP tritt nicht auf (das ist, warum ich denke, es ist eine Animation), ich habe Vista :)

Viel Glück nicht getestet.

4

Es flackert, weil Sie die alte ItemsSource wegwerfen und eine neue erstellen. Dies erfordert, dass die gesamte Bindung erneut ausgeführt wird, und die Vorlage, die jedes Element anzeigt, muss neu erstellt werden. Um den Leistungsaufwand beim erneuten Erstellen einer gesamten Liste zu vermeiden, ändern Sie einfach die einzelnen Elemente in der vorhandenen ItemsSource. Anschließend wird der Teil der DataTemplate, der an die geänderten Eigenschaften und/oder Elemente gebunden ist, automatisch aktualisiert, ohne dass die gesamte Listenansicht neu erstellt werden muss. Dadurch wird das "Flimmern" beseitigt, das Sie sehen.

Versuchen Sie, diese für die Code-Behind:

public partial class MainWindow : Window 
{ 
    private ObservableCollection<object> _items; 

    public MainWindow() 
    { 
     InitializeComponent(); 

     _items = new ObservableCollection<object>(); 
     for (int i = 0; i < 10000; i++) 
      _items.Add(i + 1); 
     listBox.ItemsSource = _items; 

    } 

    void Button_Click(object sender, RoutedEventArgs e) 
    { 
     for (int i = 0; i < _items.Count;i++) 
     { 
      if (!(_items[i] is int)) continue; 
      _items[i] = (int)_items[i] + 1; 
     } 
    } 
} 
1

+1 zu Snake, die hier die richtige Antwort hat.

dazu hinzuzufügen:

Das CheckBox-Steuerelement hat mit Storyboard-Animation eine Steuervorlage, die ein/aus, wenn die geprüften Zustand ändert das geprüfte Symbol animiert. Der Checked-Status ändert sich, wenn Sie an ObservableCollection binden und die ItemsSource neu erstellen, wodurch neue Checkboxen erstellt werden (mit IsChecked = false) und an Ihr ViewModel gebunden werden (was wahrscheinlich zu IsChecked = True führt).

Um diese Funktion zu deaktivieren, können Sie entweder ändern, wie Sie eine ObservableCollection ausfüllen, oder wenn dies nicht möglich ist, können Sie die Vorlage/den Stil der Checkbox ändern.

Reverse Engineering der ControlTemplate von Checkbox (mit Blend oder mit einem der WPF Themes) und finden Sie diese Zeilen. Sie müssen die Dauer der beiden Animationen auf Null setzen

<!-- Inside the CheckBoxTemplate ControlTemplate --> 
<Storyboard x:Key="CheckedTrue"> 
    <DoubleAnimationUsingKeyFrames Storyboard.TargetName="CheckIcon" 
          Storyboard.TargetProperty="(UIElement.Opacity)"> 
     <SplineDoubleKeyFrame KeyTime="00:00:00.1000000" Value="1" /> 
    </DoubleAnimationUsingKeyFrames> 
</Storyboard> 
<Storyboard x:Key="CheckedFalse"> 
    <DoubleAnimationUsingKeyFrames Storyboard.TargetName="CheckIcon" 
          Storyboard.TargetProperty="(UIElement.Opacity)"> 
     <SplineDoubleKeyFrame KeyTime="00:00:00.4000000" Value="0" /> 
    </DoubleAnimationUsingKeyFrames> 
</Storyboard>