0

I want change the ListView's item background dynamicly, so I using the Timer as the event trigger. But after the timer is triggered, the background color can not refresh automatically until I resize the window. Here is my code snippet:

    public MainWindow()
    {
        InitializeComponent();
        ObservableCollection<Object> People = new ObservableCollection<Object>();
        for (int i = 0; i < 10; i++)
            People.Add(new Person());
        listView.ItemsSource = People;

        System.Timers.Timer _timer = new System.Timers.Timer(10);
        _timer.Elapsed += new System.Timers.ElapsedEventHandler(theObjectDroped);
        _timer.AutoReset = true;
        _timer.Enabled = true;
    }

    public void theObjectDroped(object source, System.Timers.ElapsedEventArgs e)
    {
        for (int i = 0; i < listView.Items.Count; i++)
        {
            Dispatcher.Invoke(new Action<int, Brush>(ModifyListViewBackground), i, Brushes.Red);
        }
    }

    private void ModifyListViewBackground(int i, Brush brush)
    {
        listView.ItemContainerGenerator.StatusChanged += (s, e) =>
        {
            ListViewItem row = listView.ItemContainerGenerator.ContainerFromIndex(i) as ListViewItem;
            if (row != null && row.Background != brush)
            {
                row.Background = brush;
            }
        };
    }
4

2 回答 2

2

分析您ModifyListViewBackground的方法 - 您仅在执行后附加事件处理程序并更改背景。

listView.ItemContainerGenerator.StatusChanged您是否在代码中的其他地方触发?如果不是,这可能是最可能的情况。另请记住,事件处理程序可以堆叠多次,因此每次触发计时器时,您都需要清理(分离)旧的事件处理程序。

尝试测试以下版本之一ModifyListViewBackground。请注意,它们更具示意性,因为我目前没有 IDE - 分离以前的事件处理程序,附加新的和触发事件:

private void ModifyListViewBackground(int i, Brush brush)  
    {  
        listView.ItemContainerGenerator.StatusChanged -=StatusChangedCompleted;
        listView.ItemContainerGenerator.StatusChanged +=StatusChangedCompleted;
        listView.ItemContainerGenerator.StatusChanged();
    }
private void StatusChangedCompleted(object source, SomeEventArgs e)
{
    ListViewItem row = listView.ItemContainerGenerator.ContainerFromIndex(i) as ListViewItem;  
    if (row != null && row.Background != brush)  
    {  
        row.Background = brush;  
    }  
}

或者,如果不需要事件处理程序,这也应该起作用:

private void ModifyListViewBackground(int i, Brush brush)  
    {  
        ListViewItem row = listView.ItemContainerGenerator.ContainerFromIndex(i) as ListViewItem;  
            if (row != null && row.Background != brush)  
            {  
                row.Background = brush;  
            }    
    }
于 2012-11-22T15:29:13.013 回答
1

在这一行中,您正在为 StatusChanged 事件设置事件处理程序:

    listView.ItemContainerGenerator.StatusChanged += (s, e) =>

当您执行诸如更改窗口大小之类的操作时会触发此事件,这就是为什么您在执行诸如调整窗口大小之类的操作时只会看到背景颜色更改的原因。

要使其在计时器事件被触发后立即工作,只需在您的ModifyListViewBackground方法中删除事件处理程序:

    private void ModifyListViewBackground(int i, Brush brush)
    {
        ListViewItem row = listView.ItemContainerGenerator.ContainerFromIndex(i) as ListViewItem;
        if (row != null && row.Background != brush)
        {
            row.Background = brush;
        }
    }

注意您的计时器设置为在 10 毫秒后触发。这是非常快的,当尝试这个时,它几乎是瞬间的。我将其设置为 1 秒(1000 毫秒),以便我可以看到超时后触发的事件。

于 2012-11-22T15:27:51.340 回答