Reputation: 2813
I have a DataGrid
associated with a List <>
of objects (ItemsSource
). In the CellEditEnding ()
event, I change the data of the linked object list. To refresh the DataGrid
, it must be refreshed:
this.DataGridFieldProperties.Items.Refresh();
Invoking the update from code within the CellEditEnding()
event throws an InvalidOperationException
.
Question:
Is there an event triggered after CellEditEnding()?
What I have tried so far
Multiple events, such as GotFocus
, ColumnDisplayIndexChanged()
, etc., and two-way bindings. But none of them works reliably and refreshing the DataGrid
in an asynchronous thread (async event with Task.Run()
)
Example
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Button Name="Btn_FillGrid" Click="Btn_FillGrid_Click"/>
<DataGrid Name="DataGrid_SOExample" Grid.Row="1" AutoGenerateColumns="False" CanUserAddRows="False" IsReadOnly="False" CellEditEnding="DataGrid_SOExample_CellEditEnding">
<DataGrid.Columns>
<DataGridTextColumn Header="Generic1"/>
<DataGridTextColumn Header="Generic2"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
public partial class Win_SOExample : Window
{
public Win_SOExample()
{
InitializeComponent();
}
private void Btn_FillGrid_Click(object sender, RoutedEventArgs e)
{
List<SoExample> soExampList = new List<SoExample>();
soExampList.Add(new SoExample() { Field1 = "Row0 Field1", Field2 = "Row0 Field2" });
soExampList.Add(new SoExample() { Field1 = "Row1 Field1", Field2 = "Row1 Field2" });
soExampList.Add(new SoExample() { Field1 = "Row2 Field1", Field2 = "Row2 Field2" });
(this.DataGrid_SOExample.Columns[0] as DataGridTextColumn).Binding = new Binding("Field1") { Mode = BindingMode.TwoWay };
(this.DataGrid_SOExample.Columns[1] as DataGridTextColumn).Binding = new Binding("Field2") { Mode = BindingMode.TwoWay };
this.DataGrid_SOExample.ItemsSource = soExampList;
}
private async void DataGrid_SOExample_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
if(e.EditAction == DataGridEditAction.Commit)
{
// after the user finished the edit, data in other rows needs to get updatet
// simple example
List<SoExample> soExampList = (this.DataGrid_SOExample.ItemsSource as List<SoExample>);
soExampList[1].Field1 = DateTime.Now.ToLongDateString();
await Task.Yield();
this.DataGrid_SOExample.Items.Refresh();
}
}
private class SoExample
{
public string Field1 { get; set; } = "";
public string Field2 { get; set; } = "";
}
}
Upvotes: 2
Views: 485
Reputation: 169400
You should implement INotifyPropertyChanged
in your SoExample
class:
private class SoExample : INotifyPropertyChanged
{
private string _field1;
public string Field1
{
get { return _field1; }
set { _field1 = value; NotifyPropertyChanged(); }
}
private string _field2;
public string Field2
{
get { return _field2; }
set { _field2 = value; NotifyPropertyChanged(); }
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] String propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Then you can set the property to a new value without refreshing:
private async void DataGrid_SOExample_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
if (e.EditAction == DataGridEditAction.Commit)
{
List<SoExample> soExampList = (this.DataGrid_SOExample.ItemsSource as List<SoExample>);
soExampList[1].Field1 = DateTime.Now.ToLongDateString();
}
}
Upvotes: 2