2

我想知道每次用户修改 WPF DataGrid 中的数据时。

我可以使用一个事件来做到这一点吗?或者我可以用来覆盖全部数据更改(添加行、删除行、修改行等)的最小事件集是什么?

4

4 回答 4

3

我知道这可能超出了您的要求,但是一旦您做到了,就很难再回头了。无论您要绑定到...某个列表,都让该项目实现 IEditableObject。这样你就不必担心任何控制/视图实现,事件等。当项目更改时,数据网格以及大量 .NET 控件会将 IsDirty 对象设置为 true。

这些不是超级好的链接,但它们会让你开始考虑维护 isDirty 标志。

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

对象编辑和 isDirty() 标志

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

这更像是我习惯的:

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

于 2012-04-26T00:12:07.240 回答
1

通常,当您使用 MVVM 时,您会将主列表绑定到 ObservableCollection,然后将所选项目绑定到特定实例。在你的 setter 中,你可以引发事件。这将是捕获数据列表的更新/添加/删除的最合乎逻辑的(阅读:我见过的最常见的方法)。

于 2012-04-25T18:54:16.373 回答
0

如果你使用 mvvm 你不需要知道什么时候“用户修改数据网格中的数据”你必须知道底层集合什么时候改变

因此,如果您使用数据表(HasChanges/RejectChanges...),那么您将拥有所有内置功能。如果您使用 poco 集合,那么您的项目至少必须实现 INotifyPropertyChanged - 如果它引发了用户修改数据。也许 IEditable 对于拒绝更改等也是一个很好的选择。

于 2012-04-26T05:37:57.173 回答
0

主窗口.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>

主窗口.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 或任何其他方式更改属性,则仅更新当前值。当需要保存数据时,只需检查任何项目是否具有任何具有不同原始值和当前值的属性。如果答案是肯定的,则应保存数据,因为自上次加载/保存以来已更改,否则数据与加载时相同,因此不需要重新保存。此外,保存时,必须将当前值复制到原始值,因为数据再次等于保存的数据,就像上次加载时一样。

于 2012-04-25T23:10:29.230 回答