Вопрос:

WPF DataGrid: немедленно сохраняйте изменения ячеек с помощью MVVM

c# wpf xaml mvvm datagrid

42 просмотра

3 ответа

163602 Репутация автора

У меня есть упрощенный DataGrid, который выглядит так:

<DataGrid AutoGenerateColumns="False" 
          ItemsSource="{Binding Parts}" 
          SelectedItem="{Binding SelectedPart}" >
    <DataGrid.Columns>
        <DataGridTextColumn Header="Name" Binding="{Binding Path=Name, Mode=TwoWay}" />
        <DataGridTemplateColumn Header="PartType" >
            <DataGridTemplateColumn.CellEditingTemplate>
                <DataTemplate>
                    <ComboBox ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=DataContext.PartTypes}" 
                              SelectedItem="{Binding PartType, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" />
                </DataTemplate>
            </DataGridTemplateColumn.CellEditingTemplate>
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding PartType}" />
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>

Моя ViewModel выглядит примерно так:

public class PartListViewModel
{
    private ObservableCollection<Part> _parts;
    public ObservableCollection<Part> Parts
    {
        get { return _parts; }
        set
        {
            _parts = value;
             OnPropertyChanged("Parts");
        }
    }

    private Part _selectedPart;
    public Part SelectedPart
    {
        get { return _selectedPart; }
        set
        {
            _selectedPart = value;
            OnPropertyChanged("SelectedPart");
        }
    }
}

Теперь я хочу, чтобы изменения в ячейках данных были немедленно сохранены в базе данных. Как это сделать в MVVM?

В настоящее время я слушаю OnCellEditEndingсобытие DataGrid и сохраняю запись в коде. Но это довольно уродливо

private void DataGrid_OnCellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
    var viewModel = (PartListViewModel) DataContext;
    viewModel.SavePart((Part) e.Row.Item);
}
Автор: juergen d Источник Размещён: 12.06.2019 05:07

Ответы (3)


1 плюс

186 Репутация автора

Вы можете сделать что-то вроде этого. (нужно добавить ссылку на System.Windows.Interactivity, вы можете скачать сборки здесь )

Затем добавьте ссылку на пространство имен в XAML. xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"

<i:Interaction.Triggers>
  <i:EventTrigger EventName="CellEditEnding">
     <i:InvokeCommandAction Command="{Binding SomeCommand}"/>
  </i:EventTrigger>
</i:Interaction.Triggers>
Автор: TheLastStark Размещён: 12.06.2019 05:13

1 плюс

42879 Репутация автора

Один из способов сделать это - использовать брокер событий, такой как EventAggregator, который поставляется с библиотеками Prism.

Когда вы добавляете каждый объект Part («модель») в коллекцию Parts, вы можете обернуть его своей собственной моделью представления (PartViewModel), тогда он может прослушивать обновления свойств в своей составной части, а затем публиковать сообщение об обновлении через посредник событий. Затем вы можете иметь службу, которая прослушивает (подписывается) это сообщение и сохраняет опубликованную полезную нагрузку (полезной нагрузкой может быть измененная часть).

Автор: slugster Размещён: 12.06.2019 06:01

0 плюса

93990 Репутация автора

Вы можете обработать PropertyChangedсобытие для всех Partобъектов в модели представления:

public class PartListViewModel
{
    private ObservableCollection<Part> _parts;
    public ObservableCollection<Part> Parts
    {
        get { return _parts; }
        set
        {
            if(_parts != null) _parts.CollectionChanged -= OnCollectionChanged;
            _parts = value;
            if (_parts != null) _parts.CollectionChanged += OnCollectionChanged;
            //OnPropertyChanged("Parts");
        }
    }

    private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        if (e.NewItems != null)
        {
            foreach (object part in e.NewItems)
            {
                (part as INotifyPropertyChanged).PropertyChanged
                    += new PropertyChangedEventHandler(PartPropertyChanged);
            }
        }

        if (e.OldItems != null)
        {
            foreach (object part in e.OldItems)
            {
                (part as INotifyPropertyChanged).PropertyChanged
                    -= new PropertyChangedEventHandler(PartPropertyChanged);
            }
        }
    }

    private void PartPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if(e.PropertyName == "PartType")
        {
            //save to database...
        }
    }
}

Это делает Partкласс для реализации, INotifyPropertyChangedконечно.

Автор: mm8 Размещён: 12.06.2019 02:48
Вопросы из категории :
32x32