c# - ListView 未使用 ObservableCollection 正确更新

标签 c# listview observablecollection dispatcher

我目前正在使用可观察集合来存储 ListView 的数据对象。将新对象添加到集合中效果很好,并且 listView 会正确更新。但是,当我尝试更改集合中某个对象的属性之一时,listView 将无法正确更新。例如,我有一个可观察的集合 DataCollection。我试试

_DataCollections.ElementAt(count).Status = "Active";

由于按下按钮,我在长时间操作之前执行此更改。 listView 不会反射(reflect)更改。所以我添加了myListView.Items.Refresh();。这是有效的,但是 listView 在 button_click 方法完成之前不会刷新,这在那时是不好的。 例如:

   button1_Click(...)
    {
      _DataCollections.ElementAt(count).Status = "Active";
      myListView.Items.Refresh();
      ExecuteLongOperation();
      _DataCollections.ElementAt(count).Status = "Finished";
      myListView.Items.Refresh();
    }

状态永远不会变为“Active”,方法完成后会直接变为“Finished”。 我也尝试过使用这样的调度程序:

button1_Click(...)
    {
      this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Background,
            (NoArgDelegate)delegate { _DataCollection.ElementAt(count).Status =  "Active"; myListView.Items.Refresh(); });

      ExecuteLongOperation();
     this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Background,
            (NoArgDelegate)delegate { _DataCollection.ElementAt(count).Status =  "Finished"; myListView.Items.Refresh(); });

    }

但是,这似乎也不能正常工作。任何提示或想法将不胜感激。

最佳答案

您必须使用适当的数据绑定(bind)技术,然后它会自动运行。

必需...

  1. 在 ObservableCollection 中的类上实现 INotifyPropertyChanged(并确保在该类上设置属性时触发事件)
  2. 在您的 ListView 的 ItemTemplate 上,确保您正在使用绑定(bind)到属性

如果您执行了这两件事,就不需要“刷新”调用或其他任何操作。设置触发 INotifyPropertyChanged 的​​属性将导致 ItemTemplate 的绑定(bind)更新。

在 ObservableCollection 中的类上实现 INotifyPropertyChanged...(如果您还不知道,请查找 BindableBase 类)

public class ToDoItem : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private string _name;
    public string Name
    {
        get { return _name; }
        set { SetProperty(ref _name, value); }
    }

    private DateTime _date;
    public DateTime Date
    {
        get { return _date; }
        set { SetProperty(ref _date, value); }
    }

    protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName]string propertyName = null)
    {
        if (object.Equals(storage, value)) return false;

        storage = value;
        this.OnPropertyChanged(propertyName);
        return true;
    }

    protected void OnPropertyChanged(string propertyName)
    {
        var eventHandler = this.PropertyChanged;
        if (eventHandler != null)
        {
            eventHandler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

您的 ListView

<ListView
    x:Name="listView">

    <ListView.ItemTemplate>
        <DataTemplate>

            <StackPanel>

                <TextBlock
                    Text="{Binding Name}"/>

                <TextBlock
                    Text="{Binding Date}"/>

            </StackPanel>

        </DataTemplate>
    </ListView.ItemTemplate>

</ListView>

您的 ObservableCollection...

private ObservableCollection<ToDoItem> _toDoItems = new ObservableCollection<ToDoItem>();

// Assign the collection to the ListView
listView.ItemsSource = _toDoItems;

向收藏作品中添加东西...

_toDoItems.Add(new ToDoItem()
{
    Name = "Item " + (_toDoItems.Count + 1),
    Date = DateTime.Now
});

更新,你所要求的,有效...

ToDoItem item = _toDoItems[randomIndex];

item.Name = "Updated " + item.Name;
item.Date = DateTime.Now;

没有调用“刷新”或任何其他需要的。项目本身会更新,而列表不会更改。

更新第 4 项之前...

Before updating Item 4

更新第 4 项后...

After updating Item 4

此处提供完整代码示例: CODE SAMPLE

关于c# - ListView 未使用 ObservableCollection 正确更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6542035/

相关文章:

C#:Func<> 而不是方法?

java - 使用 JNA 从 Win32 ListView 检索项目文本

c# - 使用复选框禁用 ListView 中的单个复选框

c# - WPF 列表框绑定(bind)

wpf - Observable Collection 没有更新数据网格

c# - 在这种多线程情况下如何编写干净的代码?

c# - 令人困惑的 "ambiguous reference"错误

android - 在 CustomAdapters 中使用条件 if(view==null)

c# - WPF - 在 UserControl 中绑定(bind) ObservableCollection 依赖属性

c# - Moq 正在读取分配给输出参数的值。如何?