这个问题是我之前提问的结果DataGrid - grid selection is reset when new Data is arrived
=============================================== ======================
我有这样的DataGrid
<DataGrid AutoGenerateColumns="True" HorizontalAlignment="Stretch" Name="dataGrid1" VerticalAlignment="Stretch" ItemsSource="{Binding DataList}" IsReadOnly="True"/>
在我的ViewModel中,我有这样的字段:
public ObservableCollection<ConsoleData> DataList { get; set; }
这种每秒调用的方法:
private void model_DataArrived(List<ConsoleData> dataList)
{
DataList.Clear();
dataList.ForEach(x => DataList.Add(x));
}
=============================================== ======================
我们已经发现,因为我调用了DataList.Clear
,所以UI控件中的选择也被清除了,我不希望这种情况发生。因此,我不应该在ConsoleData
中替换ViewModel
的实例,而应该update
这些实例。ObservableCollection
但update
注意添加/删除我猜并且没有观察到update
不是吗?那么,如果DataBinding
实例dataList.ForEach(x => DataList.Add(x));
不起作用?
当前应用程序的另一个问题是{{1}}强制数据绑定在每次迭代时执行而不是仅在结束时执行?
总体而言,做我想做的事情的正确方法是什么,因为当前的应用程序不起作用并且有太多问题......
答案 0 :(得分:1)
目前尚不清楚您计划如何更新ObservableCollection
中的项目。至少有两种方法可以做到这一点。一种方法是更新ConsoleData对象中更改的所有属性。在这种情况下,您将拥有ConsoleData实现INotifyPropertyChanged
。另一种方法是直接更新ObservableCollection
中的项目。为此,您可以使用SetItem
的{{1}}方法。这会引发MSDN documentation for SetItem
指示的ObservableCollection
事件。
由于您已表明您正在使用MVVM,因此通常接受的做法是使您的CollectionChanged
成为ConsoleDataViewModel的集合而不是ConsoleData。
当前应用程序的另一个问题是
ObservableCollection
强制数据绑定在每次迭代时执行而不是仅在结束时执行?
如果您修改model_DataArrived方法而不是上面指出的clear / add,我认为您不会遇到刷新问题。
答案 1 :(得分:1)
问题是ObservableCollection在项目更改时没有通知;正如您所说,它仅在添加和删除项目时通知。为了解决这个问题,我创建了一个名为VeryObservableCollection的类。对于添加的每个对象,它将对象的NotifyPropertyChanged事件挂钩到触发CollectionChanged事件的处理程序。对于删除的每个对象,它将删除处理程序。很简单,应该解决你的问题。您只需要确保在集合中保存的对象上实现NotifyPropertyChanged。例如:
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);
}
答案 2 :(得分:0)
我认为你可以做这样的事情
private ObservableCollection<ConsoleData> dataList;
public ObservableCollection<ConsoleData> DataList
{
get {return dataList; }
set {dataList = value;}
}
您的数据操作只能访问字段dataList
。一次成功操纵部队DataBinding
更新或重新分配,以此方式强制Biding
向WPF发出通知。
应该工作。
答案 3 :(得分:0)
如果你的ConsoleData实现了INotifyPropertyChanged,你可以简单地更新它们,你会看到你的ui中的变化 - 没有选择丢失。
答案 4 :(得分:0)
好的,首先我们需要了解在Selector
控件(例如ListBox
,DataGrid
等)上作为选择来源的项目,如果删除,将会松开选择范围。
为此请使用批量添加和单一通知FastObservableCollection。
但要保留此类选择,您必须在DataGrid
和Clear
发生后将所选项目/值设置回AddRange
。