question

DyrFenrir-8858 avatar image
0 Votes"
DyrFenrir-8858 asked DyrFenrir-8858 edited

Issue with Date Picker needed to be used twice with Begin Edit and a Data Grid with WPF

This is a WPF application, using a Data Grid with Date Picker.

The goal is to click on the calendar, select a date, then the Data Grid goes in edit mode so as soon as I click on another cell, the Update is done on the database and the row is added on the grid, that part is working.

But, when I initially click on the Date Picker, select the date, because I do the Data Grid Begin Edit, the date selected is never displayed in the control, it goes in Edit mode, at this point I can still click on another cell to have the Insert in the database occur and the row added to the Data Grid, but the Date is inserted as null (I can also select the date again on the Date Picker and click on another cell to have the date added to database and the added row in the Data Grid).

Is there a way to change this behavior so the Date chosen is kept and it still goes in edit mode without me having to click again on the Date Picker, select the date again and then click on another cell for the Insert to happen?

May you help me out with this please?

Here is the code for the column creation (using a Template):

          templateColumn = new DataGridTemplateColumn();
          templateColumn.Header = "Testing date";
          FrameworkElementFactory datePickerFactoryElem = new FrameworkElementFactory(typeof(DatePicker));
          templateColumnBinding = new Binding("date_time");
          templateColumnBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
          templateColumnBinding.Mode = BindingMode.TwoWay;
          datePickerFactoryElem.AddHandler(DatePicker.SelectedDateChangedEvent, new EventHandler<SelectionChangedEventArgs>(RowEditEnding));
          datePickerFactoryElem.SetValue(DatePicker.SelectedDateProperty, templateColumnBinding);
          datePickerFactoryElem.SetValue(DatePicker.DisplayDateProperty, templateColumnBinding);
          cellTemplate.VisualTree = datePickerFactoryElem;
          templateColumn.CellTemplate = cellTemplate;
 
          DataGrid.Columns.Add(templateColumn);

Here is the code to begin the edit when I select a Date with the Date Picker:

      private void RowEditEnding(object sender, SelectionChangedEventArgs e)
     {
         DataGrid.BeginEdit();
     }

Here is the code fired when I click on another cell:

      private void DataGrid_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
     {
         if (!isManualEditCommit)
         {
             isManualEditCommit = true;
             DataGrid grid = (DataGrid)sender;
             grid.CommitEdit(DataGridEditingUnit.Row, true);
             isManualEditCommit = false;
         }
     }

     private void DataGrid_RowEditEnding(object sender, DataGridRowEditEndingEventArgs e)
     {
         DataRowView rowView = e.Row.Item as DataRowView;
         rowBeingEdited_DataGrid = rowView;
     }

     private void DataGrid_CurrentCellChanged(object sender, EventArgs e)
     {
         if (rowBeingEdited_DataGrid != null)
         {
             DataGrid.CommitEdit();

             conn = new MySqlConnection(connStr);

             MySqlCommand cmdInsert;
             MySqlCommand cmdUpdate;
             cmdUpdate = new MySqlCommand(@"UPDATE…
             SET…
             WHERE…;", conn);
             cmdUpdate.Parameters.Add("…");
             cmdUpdate.Parameters.Add("…");
             cmdInsert = new MySqlCommand(@"INSERT INTO…
             (…,
             …,)
             VALUES
             …,
             …);", conn);
             cmdInsert.Parameters.Add("…");
             cmdInsert.Parameters.Add("…");

             mySqlDataAdapter.InsertCommand = cmdInsert;
             mySqlDataAdapter.UpdateCommand = cmdUpdate;

             mySqlDataAdapter.Update(dataSet);
             conn.Close();
             conn.Dispose();

             DataGrid.ItemsSource = null;
             dataSet.Reset();

             rowBeingEdited_DataGrid.EndEdit();
             rowBeingEdited_DataGrid = null;

             conn = new MySqlConnection(connStr);
             mySqlDataAdapter = new MySqlDataAdapter(@"select * from …", conn);
             command = conn.CreateCommand();
             conn.Open();

             mySqlDataAdapter.Fill(dataSet);
             DataGrid.ItemsSource = dataSet.Tables[0].DefaultView;
             conn.Close();
             conn.Dispose();
         }

      }

Thank you for your time and help, it is greatly appreciated.

Note: Variables names and controls are named better in the original code, I tried to remove as much irrelevant information so the code would be easier to read.

dotnet-csharpwindows-wpf
· 5
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.


If the problem is caused by BeginEdit, maybe you can save the date value to some variable, call BeginEdit and then restore the value?

2 Votes 2 ·

Nice suggestion, I tried doing that, even set a timer with a few seconds to update the DatePicker value, but unfortunately, nothing seems to work, it is as if the DatePicker is no longer displaying any changes. The value is updated but never shown, maybe because the DataGrid now manage the value? I am unsure what happens at this point. The only way I found so far is to it manually again and then select another cell for the row to be added in the database, I can also not do it manually, click on another cell, the row will be added but then the date will be null.

0 Votes 0 ·

@DyrFenrir-8858
Did the date_time field implement property change notification? I'm a little confused by the description of click on the Date Picker, select the date, because I do the Data Grid Begin Edit, the date selected is removedin the question, could you give me more description for it?



0 Votes 0 ·

@DaisyTian-MSFT
The code I provided is what I used as a minimal example, excluding pre-defined code, variable declarations and the database connection string. To answer your question directly, I did not implement property change notification on date_time as I did not know this could be done, nor how to do it.

0 Votes 0 ·

To clarify the "click on the Date Picker..." part, I click on it, change the date with the calendar, then RowEditEnding gets fired, it then goes into DataGrid_CurrentCellChanged and see that if (rowBeingEdited_DataGrid != null) is null then goes back to RowEditEnding.

After, the date of the Date Picker is not updated but I am in edit mode on the Data Grid (the date is never shown in the Date Picker at this point, sorry for the confusion), clicking on any other cell will add the row and update the database, clicking on the Date Picker again will make it keep the date but then I will need to click on another cell again for the row to be added as well as the update.

0 Votes 0 ·
karenpayneoregon avatar image
1 Vote"
karenpayneoregon answered DyrFenrir-8858 edited

With WPF, best to setup a model which implements INotifyPropertyChanged then in xaml implement UpdateSourceTrigger property and set it to either LostFocus or PropertyChanged.

Super simple model

 using System;
 using System.ComponentModel;
 using System.Runtime.CompilerServices;
    
 namespace TODO
 {
     public class Employee : INotifyPropertyChanged
     {
         private string _firstName;
         public string FirstName
         {
             get => _firstName;
             set
             {
                 _firstName = value;
                 OnPropertyChanged();
             }
         }
    
         private string _lastName;
         public string LastName
         {
             get => _lastName;
             set
             {
                 _lastName = value;
                 OnPropertyChanged();
             }
         }
    
         private DateTime _hireDateTime;
    
         public DateTime HireDateTime
         {
             get => _hireDateTime;
             set
             {
                 _hireDateTime = value;
                 OnPropertyChanged();
             }
         }
    
         public event PropertyChangedEventHandler PropertyChanged;
         protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
         {
             PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
         }
     }
 }



Resource: Data binding overview (WPF .NET)



· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

@karenpayneoregon
Correct me if I am wrong, I thought this is what the following code did:

 templateColumnBinding = new Binding("date_time");
 templateColumnBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
 templateColumnBinding.Mode = BindingMode.TwoWay;

0 Votes 0 ·
karenpayneoregon avatar image
1 Vote"
karenpayneoregon answered DyrFenrir-8858 commented

Correct me if I am wrong, I thought this is what the following code did:

That is only part of what needs to be done. Note the most important thing below is the RowEditEnding event (which does an immediate save to the database) and secondly there is zero validation done while there is also a save button which does validation.

I don't have a code sample that uses DataTable containers, did away with them 10 or so years ago but I think if you look at the following code sample which is a hodgepodge project used for teaching WPF and Entity Framework.

82966-f1a.png

It does not use a date control in the data grid but that does not matter what is important in is highlighted in the xaml

83022-f1b.png

Code behind
Here this is Entity Framework, for a DataTable you need to implement this.

 private void EmployeeGrid_OnRowEditEnding(object sender, DataGridRowEditEndingEventArgs e)
 {
       
     _context.SaveChanges();
    
 }



f1a.png (14.7 KiB)
f1b.png (48.2 KiB)
· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

@karenpayneoregon
I tried what you suggested and I still have issues with the DatePicker, please note that I also have other texts columns in my original code and they are all working, for an odd reason, only the DatePicker behaves as described in the original post.

0 Votes 0 ·