【问题标题】:WPF: How can I avoid the flickering of the checked checkboxes in a ListBox or a ListView?WPF:如何避免 ListBox 或 ListView 中选中的复选框闪烁?
【发布时间】:2011-01-01 17:27:01
【问题描述】:

如何避免 WPF ListBox 或 ListView 中选中的复选框闪烁?通过单击刷新按钮或滚动列表框,可以使用下面的代码复制它。如果 IsChecked 为 false,则不会闪烁。

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

【问题讨论】:

    标签: wpf rendering


    【解决方案1】:

    它正在闪烁,因为您正在丢弃旧的 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;
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      你的意思是复选框被选中?我认为您在选中/设置复选框时需要更改动画。

      它不会出现在 Windows XP 上(这就是我认为它是动画的原因),我没有测试过 Vista :)

      祝你好运。

      【讨论】:

        【解决方案3】:

        +1 给在这里有正确答案的 Snake。

        补充:

        复选框控件有一个带有故事板动画的控制模板,当检查状态发生变化时,主板动画动画在/关闭检查的图标。当您绑定到 ObservableCollection 并重新创建 ItemsSource 时,Checked 状态会发生变化,这会导致创建新的复选框(IsChecked=false)并绑定到您的 ViewModel(这可能导致 IsChecked=True)。

        要禁用此“功能”,您可以修改填充 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>
        

        【讨论】:

          猜你喜欢
          • 2011-08-30
          • 1970-01-01
          • 2023-03-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-04-02
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多