ユーザーが WPF DataGrid のデータを変更するたびに知りたいです。
そのために使用できる単一のイベントはありますか? または、データ変更の完全なセット (行の追加、行の削除、行の変更など) をカバーするために使用できるイベントの最小セットは何ですか?
これはおそらくあなたが求めている以上のものであることはわかっていますが、一度それを行うと、元に戻すのは困難です. あなたがバインドしているものは何でも...いくつかのリスト、そのアイテムにIEditableObjectを実装させます。そうすれば、コントロール/ビューの実装、イベント セットについて心配する必要がなくなります。項目が変更されると、データグリッドと多数の .NET コントロールが IsDirty オブジェクトを true に設定します。
これらは素晴らしいリンクではありませんが、isDirty フラグの維持について考え始めるきっかけとなります。
https://msdn.microsoft.com/en-us/library/system.componentmodel.ieditableobject(v=vs.110).aspx
http://bltoolkit.net/doc/EditableObjects/EditableObject.htm
これは私が慣れているものです:
通常、MVVM を使用している場合は、マスター リストを ObservableCollection にバインドしてから、選択したアイテムを特定のインスタンスにバインドします。セッター内で、イベントを発生させることができます。これは、データのリストへの更新/追加/削除をキャプチャするための最も論理的な (読み取り: 私が見た中で最も一般的な方法) でしょう。
mvvmを使用する場合、「ユーザーがデータグリッド内のデータを変更する」時期を知る必要はなく、基になるコレクションがいつ変更されるかを知る必要があります。
したがって、datatable(HasChanges / RejectChanges ...)を使用する場合は、すべてが組み込まれています。pocoコレクションを使用する場合、アイテムは少なくともINotifyPropertyChangedを実装する必要があります。たぶん、IEditableは変更を拒否するなどにも適しています。
MainWindow.xaml
<Window x:Class="WpfApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication"
Title="MainWindow" Height="350" Width="525">
<DataGrid x:Name="dataGrid" AutoGeneratingColumn="OnAutoGeneratingColumn">
<DataGrid.Resources>
<Style TargetType="DataGridCell">
<EventSetter Event="Binding.SourceUpdated" Handler="OnDataGridCellSourceUpdated"/>
<EventSetter Event="Binding.TargetUpdated" Handler="OnDataGridCellTargetUpdated"/>
</Style>
</DataGrid.Resources>
</DataGrid>
</Window>
MainWindow.xaml.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.dataGrid.ItemsSource = new ObservableCollection<Person>()
{
new Person() { Name = "John", Surname = "Doe" },
new Person() { Name = "Jane", Surname = "Doe" }
};
}
private void OnAutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
var dataGridBoundColumn = e.Column as DataGridBoundColumn;
if (dataGridBoundColumn != null)
{
var binding = dataGridBoundColumn.Binding as Binding;
if (binding != null)
{
binding.NotifyOnSourceUpdated = true;
binding.NotifyOnTargetUpdated = true;
}
}
}
private void OnDataGridCellSourceUpdated(object sender, DataTransferEventArgs e)
{
this.OnDataGridCellChanged((DataGridCell)sender);
}
private void OnDataGridCellTargetUpdated(object sender, DataTransferEventArgs e)
{
this.OnDataGridCellChanged((DataGridCell)sender);
}
private void OnDataGridCellChanged(DataGridCell dataGridCell)
{
// DataContext is MS.Internal.NamedObject for NewItemPlaceholder row.
var person = dataGridCell.DataContext as Person;
if (person != null)
{
var propertyName = ((Binding)((DataGridBoundColumn)dataGridCell.Column).Binding).Path.Path;
var propertyValue = TypeDescriptor.GetProperties(person)[propertyName].GetValue(person);
// TODO: do some logic here.
}
}
}
これは、Person (単なる POCO) インスタンス、プロパティ名、およびプロパティ値に基づく複雑な DataGridCell 書式設定に使用したものです。
ただし、いつデータを保存するかを知りたい場合に MVVM を使用する場合、これを行う最善の方法は、ビュー モデル/モデルのすべての編集可能なプロパティの元の値と現在の値を取得することです。データが読み込まれると、元の値と現在の値は等しくなり、プロパティが DataGrid またはその他の方法で変更された場合、現在の値のみが更新されます。データを保存する必要がある場合は、元の値と現在の値が異なるプロパティがあるアイテムがないかどうかを確認してください。答えが「はい」の場合、前回のロード/保存以降にデータが変更されているため、データを保存する必要があります。それ以外の場合、データはロードされたときと同じであるため、新たに保存する必要はありません。また、保存時には、最後にロードされたときと同じように、データが保存されたデータと再び同じになるため、現在の値を元の値にコピーする必要があります。