2012-04-25 2 views
2

Я хотел бы знать каждый раз, когда пользователь изменяет данные в WPF DataGrid.Каков наилучший способ узнать, изменил ли пользователь данные в DataGrid?

Есть ли одно событие, которое я могу использовать для этого? Или какой минимальный набор событий я могу использовать для покрытия полного набора изменений данных (добавить строку, удалить строку, изменить строку и т. Д.)?

+0

Используете ли вы шаблон дизайна, например MVVM или MVC, или просто выполняете прямой код? – Josh

+0

Я использую mvvm. Я хочу использовать это, чтобы иметь возможность сказать, когда мне нужно сохранить данные. –

+0

http://msdn.microsoft.com/en-us/library/system.windows.controls.datagrid.selectedcellschanged.aspx – Habib

ответ

1

Обычно, когда вы используете MVVM, вы связываете основной список с ObservableCollection, а затем выбранный элемент в конкретный экземпляр. Внутри ваших сеттеров вы можете поднимать события. Это было бы наиболее логичным (прочитайте: наиболее распространенный метод, который я видел) для захвата обновлений/добавления/удаления в список данных.

0

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. 
     } 
    } 
} 

Это то, что я использовал для некоторых сложных DataGridCell форматирования на основе Person (только некоторые POCO), например , имя свойства и значение свойства.

Но если вы хотите знать, когда сохранять данные и использовать MVVM, лучшим способом сделать это было бы иметь исходное значение и текущее значение для каждого редактируемого свойства в вашей модели/модели представления. Когда данные будут загружены, исходное и текущее значение будут равны, и если свойство будет изменено с помощью DataGrid или любым другим способом, обновится только текущее значение. Когда данные необходимо сохранить, просто проверьте, имеет ли какой-либо элемент какое-либо свойство, имеющее другое исходное и текущее значение. Если да, то данные должны быть сохранены, поскольку они были изменены с момента последней загрузки/сохранения, в противном случае данные будут такими же, как при загрузке, поэтому никаких новых изменений не требуется. Кроме того, при сохранении текущие значения должны быть скопированы в исходные значения, поскольку данные снова равны сохраненным данным, например, когда они были загружены в последний раз.

3

Я знаю, что это, вероятно, больше, чем вы просите, но как только вы это сделаете, трудно вернуться назад. Независимо от того, что вы связываете с ... некоторым списком, этот элемент реализует IEditableObject. таким образом вам не придется когда-либо беспокоиться о том, какая реализация/просмотр реализации, события ets. Когда элемент изменен, datagrid, а также множество элементов управления .NET установят для объекта IsDirty значение true.

Это не очень хорошие ссылки, но они заставят вас начать думать о сохранении isDirty flag.

https://msdn.microsoft.com/en-us/library/system.componentmodel.ieditableobject(v=vs.110).aspx

object editing and isDirty() flag

http://bltoolkit.net/doc/EditableObjects/EditableObject.htm

это больше того, что я привык:

https://stackoverflow.com/a/805695/452941

+0

Ваша ссылка MSDN мертва. –

+0

Я исправил ссылку – Sentry

0

если вы используете MVVM вам не нужно знать, когда " пользователь модифицирует данные в сетке данных », вы должны знать, когда изменение базовой коллекции.

поэтому, если вы используете datatable (HasChanges/RejectChanges ...), у вас есть все встроенные. Если вы используете коллекцию poco, то ваши элементы должны, по крайней мере, реализовать INotifyPropertyChanged, - если это привело к изменению данных пользователя. Может быть, IEditable является хорошим тоже для отклонения изменений и так далее.

Смежные вопросы