简体   繁体   中英

WPF Databinding: Updating an Item in an ObservableCollection

I am trying to reflect an ObservableCollection's changes in a WPF DataGrid. Additions and removals to the list work great, but I'm stuck on edits.

I initialize the ObservableCollection in my constructor:

public MainWindow()
{
    this.InitializeComponent();

    this.itemList = new ObservableCollection<Item>();
    DataGrid.ItemsSource = this.itemList;
    DataGrid.DataContext = this.itemList;
}

I have a class that implements INotifyPropertyChanged:

public class Item : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public string FirstName { get; set; }

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        var handler = this.PropertyChanged;

        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Additions to the ObservableCollection work great:

Application.Current.Dispatcher.Invoke((Action) (() => this.itemList.Add(new Item { FirstName = firstName })));

TL;DR

My question is, how do I update an item in the list while allowing databinding to update my GridView?

I have not been able to achieve it, except by shamefully removing and re-adding the item:

item.FirstName = newFirstName;
Application.Current.Dispatcher.Invoke((Action)(() => this.itemList.Remove(item)));
Application.Current.Dispatcher.Invoke((Action)(() => this.itemList.Add(item)));

UPDATE

Per comment request, here is more code on how I'm doing the update:

foreach (var thisItem in this.itemList)
{
    var item = thisItem;

    if (string.IsNullOrEmpty(item.FirstName))
    {
        continue;
    }

    var newFirstName = "Joe";

    item.FirstName = newFirstName; // If I stop here, the collection updates but not the UI. Updating the UI happens with the below calls.

    Application.Current.Dispatcher.Invoke((Action)(() => this.itemList.Remove(item)));
    Application.Current.Dispatcher.Invoke((Action)(() => this.itemList.Add(item)));

    break;
}

The implementation of INotifyPropertyChanged in your Item object is not complete. There's actually no notification of change on the FirstName property. The FirstName property should be:

private string _firstName;
public string FirstName 
{ 
    get{return _firstName;}
    set
    {
        if (_firstName == value) return;
        _firstName = value;
        OnPropertyChanged("FirstName");
    }
}

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