2010-01-05 37 views
7

如何避免在WPF ListBox或ListView中檢查複選框的閃爍?可以通過點擊刷新按鈕或滾動列表框來重現下面的代碼。如果IsChecked爲false,則不閃爍。WPF:如何避免ListBox或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; 
     } 
    } 
} 

回答

2

你的意思複選框被檢查?我想你在選中/設置複選框時需要更改動畫。

它不能在Windows XP中出現(這就是爲什麼我認爲這是一個動畫),我還沒有測試Vista的:)

好運。

4

這是閃爍,因爲你拋出舊的ItemsSource並創建一個新的。這要求重做所有的綁定,並且顯示每個項目的模板需要被重新創建。爲了避免重新創建整個列表的性能開銷,只需修改現有ItemsSource中的各個元素。然後,綁定到已更改屬性和/或項目的DataTemplate部分將自動更新,無需重新創建整個列表視圖。這樣做將消除你所看到的「閃爍」。

嘗試此代碼隱藏:

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到蛇誰在這裏有正確的答案。

要添加到這樣的:

CheckBox控件與故事板的動畫的控制模板,以動畫的開/關的選中狀態的變化時所檢查的圖標。 Checked狀態隨着您綁定到ObservableCollection而改變,並重新創建導致新Checkboxes被創建(使用IsChecked = false)並綁定到ViewModel(可能導致IsChecked = True)的ItemsSource。

要禁用此「功能」,您可以修改填充ObservableCollection的方式,或者如果這不可行,可以更改複選框的模板/樣式。

只需對Checkbox的ControlTemplate進行逆向工程(使用混合或使用其中一種WPF主題)並找到這些行即可。您需要將兩個動畫的持續時間設置爲零

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