2010-01-05 7 views
7

Come posso evitare lo sfarfallio delle caselle di controllo selezionate in un ListBox WPF o ListView? Può essere riprodotto con il codice sottostante facendo clic sul pulsante Aggiorna o scorrendo la casella di riepilogo. Se IsChecked è falso, non sfarfalla.WPF: Come posso evitare lo sfarfallio delle caselle di controllo selezionate in un ListBox o un ListView?

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; 
     } 
    } 
} 

risposta

2

Vuoi dire casella di essere controllato? Penso che sia necessario modificare l'animazione quando si seleziona/si seleziona la casella di controllo.

Non si verifica in Windows XP (è per questo che penso che sia un'animazione), non ho ancora testato Vista :)

Buona fortuna.

4

Sfarfallio perché si sta buttando via la vecchia ItemsSource e ne si crea una nuova. Ciò richiede il ripristino di tutto il binding e il modello che visualizza ciascun elemento deve essere ricreato. Per evitare il sovraccarico delle prestazioni di ricreare un intero elenco, è sufficiente modificare i singoli elementi nell'elemento ItemsSource esistente. Quindi la parte di DataTemplate associata alle proprietà e/o agli elementi modificati si aggiornerà automaticamente senza la necessità di ricreare l'intera visualizzazione elenco. Fare questo eliminerà il "flicker" che stai vedendo.

Prova questo per il codebehind:

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 al serpente che ha la risposta giusta qui.

Per aggiungere a questo:

Il controllo CheckBox ha un modello di controllo con l'animazione storyboard che anima l'icona controllare on/off quando cambia lo stato controllato. Lo stato controllato cambia quando si esegue l'associazione a ObservableCollection e si ricrea l'oggetto ItemsSource che causa la creazione di nuove checkbox (con IsChecked = false) e associato a ViewModel (che probabilmente risulta in IsChecked = True).

Per disabilitare questa 'funzione' è possibile modificare la modalità di compilazione di una ObservableCollection oppure, se ciò non è possibile, è possibile modificare il modello/lo stile della casella di controllo.

Basta eseguire il reverse engineering del ControlTemplate della casella di controllo (utilizzando la fusione o utilizzando uno dei temi WPF) e trovare queste righe. è necessario impostare la durata delle due animazioni su zero

<!-- 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> 
Problemi correlati