4981

WPF DataGrid RowEditEnding Event to call Update

Question:

I am using WPF . . . datagrid bound to a database via the VisualStudio IDE drag and drop, and found a way to have my datagrid update and add to the database in real time using the RowEditEnding event thusly:

private void Update_WatchList(object sender, DataGridRowEditEndingEventArgs e) { UpdateWatchList(); } private void UpdateWatchList() { dsDocControlTableAdapters.DocumentWatchListTableAdapter ta = new dsDocControlTableAdapters.DocumentWatchListTableAdapter(); try { DataRowView dr = (DataRowView)documentWatchListDataGrid.SelectedItem; dsDocControl.DocumentWatchListRow dr1 = (dsDocControl.DocumentWatchListRow)dr.Row; dr1.EndEdit(); if (dr1.RowState == DataRowState.Detached) dsDocControl.DocumentWatchList.AddDocumentWatchListRow(dr1); ta.Update(dr1); } catch (Exception ex) { MessageBox.Show("Error UpdateWatchList:\n" + ex.Message); } }

This was the result of much trial and error (during which time I missed, rescheduled and missed again a dental appointment) but somehow stumbled across the need to call EndEdit() on the row for the RowState to be updated to either Modified or Detached. Is this the expected sequence of operations for what seems to be a very normal use case, or is there a better way to do this?

I had started to go the route of adding a CollectionChanged event handler for the added rows, but could not get it to work probably because I don't properly use the ObservableCollection:

private void documentWatchListDataGrid_Loaded(object sender, RoutedEventArgs e) { var dg = (DataGrid)sender; if(dg==null || dg.ItemsSource == null) return; var sourceCollection = dg.ItemsSource as ObservableCollection<DataRow>; if (sourceCollection == null) return; //sourceCollection.CollectionChanged += new NotifyCollectionChangedEventHandler(Update_WatchList); // never gets called }

The line that adds the handler is commented out because I used the handler as the RowEditEnding (in the first code block) but regardless it never to to that point because sourceCollection was always null.

My question is, what is the best practices way to do this seemingly simple thing: update in real time as each row is changed or added in a WPF datagrid control?

Answer1:

<blockquote>

Is this the expected sequence of operations for what seems to be a very normal use case, or is there a better way to do this?

</blockquote>

No, that is not the normal method of working with DataGrids in WPF. That looks like it may be normal for WinForms, but not WPF. :)

The typical method of binding a DataGrid.ItemsSouce is to build a class that inherits INotifyPropertyChanged to represent each row of data, and bind DataGrid.ItemsSource to an ObservableCollection<T> of that class

For example, you may have something like

public class WatchListModel : INotifyPropertyChanged { // Whatever properties here public string Id { get; set; } public string Name { get; set; } }

This class should implement <a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged(v=vs.110).aspx" rel="nofollow">INotifyPropertyChanged</a>, and properties should raise change notifications, however I've left it out for simplicity. If you need an example, check out <a href="https://stackoverflow.com/a/6063929/302677" rel="nofollow">here</a>.

Then you'd have an ObservableCollection<WatchListModel> that you would be binding your DataGrid.ItemsSource too

public ObservableCollection<WatchListModel> WatchListCollection { get; set; }

and

<DataGrid ItemsSource="{Binding WatchListCollection}" ... />

And if you wanted real-time updates, you'd add a collection changed event handler for WatchListCollection to handle add/remove, and add a property changed handler to each item to handle when its modified

public MyViewModel() { WatchListCollection = new ObservableCollection<WatchListModel>(); // Hook up initial changed handler. Could also be done in setter WatchListCollection.CollectionChanged += WatchListCollection_CollectionChanged; } void WatchListCollection_CollectionChanged(object sender, CollectionChangedEventArgs e) { // if new itmes get added, attach change handlers to them if (e.NewItems != null) foreach(WatchListModel item in e.NewItems) item.PropertyChanged += WatchListModel_PropertyChanged; // if items got removed, detach change handlers if (e.OldItems != null) foreach(WatchListModel item in e.OldItems) item.PropertyChanged -= WatchListModel_PropertyChanged; // Process Add/Remove here } void WatchListModel_PropertyChanged(object sender, PropertyChangedEventArgs e) { // Process Update here }

That would be the proper WPF way to do it :)

Recommend

  • Complicated Average calculation in sql server 2008
  • What method is called when PreferenceActivity saves values
  • Mutex locking when shared memory is only read
  • Fields not getting sorted in alphabetical order in elasticsearch
  • Scaled image in NSImageView looks bad with layer-backing on
  • Postgres UTC to Java ZonedDateTime
  • How to use for loop in XSLT and get node values based on the iteration
  • MEANJS: Security in SocketIO
  • ASP.NET MVC 3 LoadingElementDuration not working?
  • How to add satellite assemblies to a project in Visual Studio
  • How to append distinct records from one table to another
  • Identify item type when handling event in Exchange Web Services (EWS)
  • Is it possible to generate a unique numeric value for each row in an iSeries table without looping?
  • overlapping appointments using the entity framework
  • C++ - Is destructor called when a vector holds objects?
  • php show all images in directory and sort by last modified
  • EF 4.1 DBContext AutoDetectChangesEnabled
  • Add dynamic data to line chart from mysql database with highcharts
  • Row to Column conversion in Talend
  • PLSQL: Get number of records updated vs inserted when a merge statement is used
  • Low TTL with Leveled Compaction, should I reduce gc_grace_seconds to improve read performance withou
  • Query to find the duplicates between the name and number in table
  • gspread or such: help me get cell coordinates (not value)
  • MongoDb aggregation
  • Functions in global context
  • recyclerView does not call the onBindViewHolder when scroll in the view
  • Is possible to count alias result on mysql
  • Check if a string to interpolate provides expected placeholders
  • Display Images one by one with next and previous functionality
  • align graphs with different xlab
  • Unanticipated behavior
  • VB.net deserialize, JSON Conversion from type 'Dictionary(Of String,Object)' to type '
  • using conditional logic : check if record exists; if it does, update it, if not, create it
  • Why joiner is not used after Sequence generator or Update statergy
  • Change div Background jquery
  • How does Linux kernel interrupt the application?
  • Can't mass-assign protected attributes when import data from csv file
  • Busy indicator not showing up in wpf window [duplicate]
  • Unable to use reactive element in my shiny app
  • Why do underscore prefixed variables exist?