use*_*491 8 c# listview dispatcher observablecollection
我目前正在使用一个可观察的集合来存储我的ListView数据对象.将新对象添加到集合中工作正常,listView正确更新.但是,当我尝试更改集合中对象的某个属性时,listView将无法正确更新.例如,我有一个可观察的集合DataCollection.我试试
_DataCollections.ElementAt(count).Status = "Active";
Run Code Online (Sandbox Code Playgroud)
由于按下按钮,我在长时间操作之前执行此更改.listView不会反映更改.所以我补充一下myListView.Items.Refresh(); 这是有效的,但是在button_click方法完成之前,listView不会刷新,这在那时是不行的.例如:
button1_Click(...)
{
_DataCollections.ElementAt(count).Status = "Active";
myListView.Items.Refresh();
ExecuteLongOperation();
_DataCollections.ElementAt(count).Status = "Finished";
myListView.Items.Refresh();
}
Run Code Online (Sandbox Code Playgroud)
状态将永远不会转到"活动",它将在方法完成后直接转到"已完成".我也尝试使用这样的调度程序:
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(); });
}
Run Code Online (Sandbox Code Playgroud)
但是,这似乎也不正常.任何提示或想法将不胜感激.
您必须使用适当的数据绑定技术,然后这将自动运行。
必需的...
如果你做了这两件事,就不需要“刷新”调用或其他任何东西。设置触发 INotifyPropertyChanged 的属性将导致 ItemTemplate 的 Binding 更新。
在 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));
}
}
}
Run Code Online (Sandbox Code Playgroud)
你的列表视图
<ListView
x:Name="listView">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock
Text="{Binding Name}"/>
<TextBlock
Text="{Binding Date}"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Run Code Online (Sandbox Code Playgroud)
你的 ObservableCollection...
private ObservableCollection<ToDoItem> _toDoItems = new ObservableCollection<ToDoItem>();
// Assign the collection to the ListView
listView.ItemsSource = _toDoItems;
Run Code Online (Sandbox Code Playgroud)
将东西添加到集合中工作...
_toDoItems.Add(new ToDoItem()
{
Name = "Item " + (_toDoItems.Count + 1),
Date = DateTime.Now
});
Run Code Online (Sandbox Code Playgroud)
和更新,你所要求的,工作......
ToDoItem item = _toDoItems[randomIndex];
item.Name = "Updated " + item.Name;
item.Date = DateTime.Now;
Run Code Online (Sandbox Code Playgroud)
无需调用“刷新”或其他任何需要。项目本身会更新,列表不会改变。
在更新第 4 项之前...
更新第 4 项后...
此处提供完整代码示例: 代码示例
为了解决这个问题,我创建了一个名为 VeryObservableCollection 的类。对于您添加的每个对象,它会将对象的 NotifyPropertyChanged 事件挂接到触发 CollectionChanged 事件的处理程序。对于删除的每个对象,它都会删除处理程序。非常简单,并且会给你你想要的。部分代码:
public class VeryObservableCollection<T> : ObservableCollection<T>
/// <summary>
/// Override for setting item
/// </summary>
/// <param name="index">Index</param>
/// <param name="item">Item</param>
protected override void SetItem(int index, T item)
{
try
{
INotifyPropertyChanged propOld = Items[index] as INotifyPropertyChanged;
if (propOld != null)
propOld.PropertyChanged -= new PropertyChangedEventHandler(Affecting_PropertyChanged);
}
catch (Exception ex)
{
Exception ex2 = ex.InnerException;
}
INotifyPropertyChanged propNew = item as INotifyPropertyChanged;
if (propNew != null)
propNew.PropertyChanged += new PropertyChangedEventHandler(Affecting_PropertyChanged);
base.SetItem(index, item);
}
Run Code Online (Sandbox Code Playgroud)