简体   繁体   中英

Databinding + DataGrid - how to connect?

This question is the result of my previous question DataGrid - grid selection is reset when new Data is arrived

=====================================================================

I have such DataGrid

<DataGrid AutoGenerateColumns="True" HorizontalAlignment="Stretch" Name="dataGrid1" VerticalAlignment="Stretch" ItemsSource="{Binding DataList}" IsReadOnly="True"/>

In my ViewModel I have such field:

public ObservableCollection<ConsoleData> DataList { get; set; }

And such method which is called every second:

private void model_DataArrived(List<ConsoleData> dataList)
{
    DataList.Clear();
    dataList.ForEach(x => DataList.Add(x));
}

=====================================================================

We have figured out that because I call DataList.Clear the selection in the UI control is cleared as well and I don't want this to happen. So likely I should not replace instances of ConsoleData in ViewModel , instead of that I should update these instances.

But ObservableCollection observes for add/remove I guess and doesn't observe for update isn't? So if I will update instances DataBinding will not work?

Another problem with the current application is that dataList.ForEach(x => DataList.Add(x)); forces databinding to execute on each iteration instead of executing only at the end?

Overall what is the right way to do what I want to do because current application doesn't work and has too many problems...

It's not clear how you are planning on updating an item in your ObservableCollection . There are at least two ways to do this. One way is to update all the properties that are changed in a ConsoleData object. In this case, you would have ConsoleData implement INotifyPropertyChanged . Another way is a direct update of item in the ObservableCollection . To do this, you could use the SetItem method of the ObservableCollection . This will raise the CollectionChanged event as the MSDN documentation for SetItem indicates.

Since you have indicated that you are using MVVM, the generally accepted thing to do would be to make your ObservableCollection be a collection of ConsoleDataViewModel instead of ConsoleData.

Another problem with the current application is that dataList.ForEach(x => DataList.Add(x)); forces databinding to execute on each iteration instead of executing only at the end?

I don't think you will have the refresh problem if you modify your model_DataArrived method to update instead of clear/add as indicated above.

The problem is the ObservableCollection not notifying when an item is changed; it notifies only when items are added and removed, as you say. To solve this problem I created a class I call VeryObservableCollection. For each object added, it hooks the object's NotifyPropertyChanged event to a handler that triggers a CollectionChanged event. For each object removed, it removes the handler. Very simple and should solve your issue. You just need to make sure you implement NotifyPropertyChanged on the objects held in the collection. For example:

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

I think you can do something like this

private ObservableCollection<ConsoleData> dataList;
public ObservableCollection<ConsoleData> DataList 
{ 
   get {return dataList; } 
   set {dataList = value;} 
}

And your data manipulations access only the field dataList . One time fiished manipulation force DataBinding to update, or reassign it, forcing in this way Biding to raise notification to WPF.

Should work.

如果你的ConsoleData实现了INotifyPropertyChanged,你可以简单地更新这些,你会看到你的ui中的变化 - 没有选择丢失。

OK first we need to understand that an item which was the source of selection on any Selector controls such as ListBox , DataGrid etc., if removed, will loose the selection.

For this please use a bulk adding and single notifying FastObservableCollection .

But to mainain such selection, you will have to set the selected item / value back to the DataGrid once Clear and AddRange takes place.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM