Форум программистов, компьютерный форум, киберфорум
C#: WPF, UWP и Silverlight
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.72/46: Рейтинг темы: голосов - 46, средняя оценка - 4.72
13 / 10 / 3
Регистрация: 29.03.2018
Сообщений: 95

Обновление ObservableCollection при изменение свойства элемента

27.07.2019, 18:46. Показов 9920. Ответов 18
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Забиндил ItemsSource в DataGrid на ObservableCollection<T>, но почему-то данные в DataGrid изменяются только при добавление или удаление элемента, а при изменение свойства элемента не меняются. Что можно с этим поделать?
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
27.07.2019, 18:46
Ответы с готовыми решениями:

Изменение ObservableCollection: автоматическое изменение свойства при изменении в DataGrid
Здравствуйте. Имеется коллекция на 35 параметров. Значения 2 главных параметров складываются из определенных сумм остальных. Вывожу...

Перехватить изменение в ObservableCollection, связанной с твоим Control посредством свойства зависимости
Когда к ItemsControl привязываешь ObservableCollection посредством ItemsSource и она изменяется, эти изменения отображаются на экране. Хотя...

Удаление, изменение элемента ObservableCollection
Добрый вечер! Не могу разобраться, не нашел нормального рабочего примера, чтобы можно было изменять конкретный элемент в коллекции или...

18
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,569
27.07.2019, 18:59
У элемента реализован интерфейс INPC?
1
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16115 / 11236 / 2887
Регистрация: 21.04.2018
Сообщений: 33,037
Записей в блоге: 2
27.07.2019, 19:23
Цитата Сообщение от Dimasikkk1 Посмотреть сообщение
Что можно с этим поделать?
Есть два интерфейса INCC (INotifyCollectionChanged Interface) - для коллекций. Он отвечает за отображения изменений в самой коллекции: добавлении элементов, удалении, вставки, перестановки и т.д. Из дефолтных Net коллекций этот интерфейс, насколько знаю, реализован (частично) только в ObservableCollection.

Второй интерфейс, это INPC (INotifyPropertyChanged Interface) - он отвечает за отображение изменений значений свойств объектов.

То есть в коллекции для полного отображения изменений нужно реализация обоих интерфейсов: для самой коллекции - INCC (это у вас реализовано использованием ObservableCollection) и для элементов коллекции - INPC. Второй у вас не реализован.
1
 Аватар для skilllab
296 / 236 / 58
Регистрация: 03.02.2011
Сообщений: 2,045
Записей в блоге: 1
28.07.2019, 00:01
Цитата Сообщение от Dimasikkk1 Посмотреть сообщение
Что можно с этим поделать?
https://www.cyberforum.ru/blog... g5134.html
1
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16115 / 11236 / 2887
Регистрация: 21.04.2018
Сообщений: 33,037
Записей в блоге: 2
28.07.2019, 15:00
Лучший ответ Сообщение было отмечено Dimasikkk1 как решение

Решение

Цитата Сообщение от skilllab Посмотреть сообщение
https://www.cyberforum.ru/blogs/153077/blog5134.html
А для чего эта лишняя сущность?
C#
1
2
public class FullyObservableCollection<T> : ObservableCollection<T>
    where T : INotifyPropertyChanged
То есть у типа элементов уже и так есть реализация INPC. Значит изменения значения элементов в ObservableCollection<T> будут в WPF отображаться.

Добавлено через 3 минуты
И это событие ItemPropertyChanged для кого предназначено?
1
13 / 10 / 3
Регистрация: 29.03.2018
Сообщений: 95
28.07.2019, 16:44  [ТС]
Хорошо что вы это заметили, я добавлял
C#
1
2
    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged([CallerMemberName] string prop = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop));
, но забывал добавить " : INotifyPropertyChanged" после имени класса. Всё заработало с обычной ObservableCollection!
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16115 / 11236 / 2887
Регистрация: 21.04.2018
Сообщений: 33,037
Записей в блоге: 2
28.07.2019, 17:31
Лучший ответ Сообщение было отмечено Dimasikkk1 как решение

Решение

Цитата Сообщение от Dimasikkk1 Посмотреть сообщение
я добавлял
Советую, чтобы не повторять код - создать базовую реализацию класса с INPC и от неё наследовать свои классы.
Я в основном использую реализацию из поста Новая реализация OnPropertyChangedClass
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
    /// <summary>Базовый класс с реализацией INPC </summary>
    public abstract class OnPropertyChangedClass : INotifyPropertyChanged
    {
        #region Событие PropertyChanged
        /// <summary>Событие для извещения об изменения свойства</summary>
        public event PropertyChangedEventHandler PropertyChanged;
        #endregion
 
        #region Методы вызова события PropertyChanged
        /// <summary>Метод для вызова события извещения об изменении свойства</summary>
        /// <param name="propertyName">Изменившееся свойство</param>
        public void OnPropertyChanged([CallerMemberName]string propertyName = "")
            => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
 
        /// <summary>Метод для вызова события извещения об изменении списка свойств</summary>
        /// <param name="propList">Список имён свойств</param>
        public void OnPropertyChanged(IEnumerable<string> propList)
        {
            foreach (string propertyName in propList.Where(name => !string.IsNullOrWhiteSpace(name)))
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        /// <summary>Метод для вызова события извещения об изменении перечня свойств</summary>
        /// <param name="propList">Список имён свойств</param>
        public void OnPropertyChanged(params string[] propList)
        {
            foreach (string propertyName in propList.Where(name => !string.IsNullOrWhiteSpace(name)))
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
 
        /// <summary>Метод для вызова события извещения об изменении всех свойств</summary>
        /// <param name="propList">Список свойств</param>
        public void OnAllPropertyChanged()
            => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(null));
 
        #endregion
 
        #region Виртуальные защищённые методы для изменения значений свойств
        /// <summary>Виртуальный метод определяющий изменения в значении поля значения свойства</summary>
        /// <param name="fieldProperty">Ссылка на поле значения свойства</param>
        /// <param name="newValue">Новое значение</param>
        /// <param name="propertyName">Название свойства</param>
        protected virtual void SetProperty<T>(ref T fieldProperty, T newValue, [CallerMemberName]string propertyName = "")
        {
            if ((fieldProperty != null && !fieldProperty.Equals(newValue)) || (fieldProperty == null && newValue != null))
                PropertyNewValue(ref fieldProperty, newValue, propertyName);
        }
 
        /// <summary>Виртуальный метод изменяющий значение поля значения свойства</summary>
        /// <param name="fieldProperty">Ссылка на поле значения свойства</param>
        /// <param name="newValue">Новое значение</param>
        /// <param name="propertyName">Название свойства</param>
        protected virtual void PropertyNewValue<T>(ref T fieldProperty, T newValue, string propertyName)
        {
            fieldProperty = newValue;
            OnPropertyChanged(propertyName);
        }
        #endregion
    }
4
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16115 / 11236 / 2887
Регистрация: 21.04.2018
Сообщений: 33,037
Записей в блоге: 2
16.04.2022, 14:38
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Я в основном использую реализацию из поста Новая реализация OnPropertyChangedClass
Поправка.
Сейчас использую реализации отсюда: Простые реализации для тем на форуме.
1
13 / 10 / 3
Регистрация: 29.03.2018
Сообщений: 95
16.04.2022, 15:01  [ТС]
Я уже перешёл на reactiveui с inpc
1
5 / 5 / 0
Регистрация: 11.09.2021
Сообщений: 578
07.12.2023, 13:13
Элд Хасп,
Как должна выглядеть полная картинка?
Используется:
- Приложение: NET Framework;
- ORM: System.Data.SQLite, EF6 (Framework);
- БД: SQLite.

Логика: пользователь вносит изменения в DataGrid, все изменения сохраняются в БД.
Вносимые изменения пользователем: добавление строк, изменения ячейки, удаление строк.


BaseInpc
https://www.cyberforum.ru/post15091910.html

Model. Index (наверное это не нужно, раз делается IndexViewModel?)
C#
1
2
3
4
5
6
7
 [Table("Indexes")]
    public class Index : BaseInpc
    {
        public int Id { get; set; }
        public string Name { get; set; }        
       
    }


ViewModel. IndexViewModel
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 [Table("Indexes")]
    public class IndexViewModel : BaseInpc
    {
        public int Id { get; set; }
        
        private string name;
        public string Name { get => name;
            set
            {
                Set(ref name, value); 
                Debug.WriteLine($"Index prop -- Name {name}");
            }
        }
 
        protected override void OnPropertyChanged(string propertyName, object oldValue, object newValue)
        {
            base.OnPropertyChanged(propertyName, oldValue, newValue);
 
            Debug.WriteLine($"OnPropertyChanged--propertyName {propertyName}");
        }
 
    }

ViewModel. IndexesViewModel
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public class IndexesViewModel : BaseInpc
    {   
        DbContextIndexes _dataContextApp;
        public IndexesViewModel()
        {
 
            this._dataContextApp = new DbContextIndexes();
            
            LoadData();
 
            Indexes.CollectionChanged += Indexes_CollectionChanged;        
        }
 
        private void Indexes_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            // throw new NotImplementedException();
            Debug.WriteLine($"Indexes_CollectionChanged");
            Debug.WriteLine($"Indexes_CollectionChanged: --- {e.Action.ToString()}");
            _dataContextApp.SaveChanges();
        }
 
        private ObservableCollection<Index> indexes;
        public ObservableCollection<Index> Indexes
        {
            get { return indexes; }
            set
            {
                Set(ref indexes, value);
                Debug.WriteLine($"ObservableCollection<Index> Indexes -- set ");
                // _dataContextApp.SaveChanges();
            }
        }
 
        public void LoadData()
        {         
            var items = this._dataContextApp.Indexes.ToList();
            Indexes = new ObservableCollection<Index>(items);
        }
 
    }

DbContextIndexes
C#
1
2
3
4
5
6
7
8
public class DbContextIndexes : DbContext
    {
        public DbContextIndexes() : base("DefaultConnection")
        {
 
        }
        public DbSet<Index> Indexes { get; set; }
    }

MainWindow.xaml
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<DataGrid Grid.Row="1"                                         
                     ItemsSource="{Binding Indexes}"
                    SelectedIndex="2"
                    AutoGenerateColumns="False"
                    CanUserAddRows="True"
                    GridLinesVisibility="Vertical"                                  
                    VerticalGridLinesBrush="DarkGray"
                     AlternatingRowBackground="LightGray"
                     >
            <DataGrid.Columns>
                <DataGridTextColumn Header="id" Binding="{Binding Id}" Width="Auto"/>
                <DataGridTextColumn Header="Имя" Binding="{Binding Name}" Width="*"/>
            </DataGrid.Columns>
        </DataGrid>

MainWindow
C#
1
2
3
4
5
6
7
8
9
10
11
public partial class MainWindow : Window
{
        public MainWindow()
        {
            InitializeComponent();
 
            this.DataContext = new IndexesViewModel();
        }
 
 
}
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16115 / 11236 / 2887
Регистрация: 21.04.2018
Сообщений: 33,037
Записей в блоге: 2
07.12.2023, 23:07
Цитата Сообщение от dev3214 Посмотреть сообщение
Логика: пользователь вносит изменения в DataGrid, все изменения сохраняются в БД.
В какой момент?
Явно по клику на кнопке?
Автоматом при потере фокуса строкой?
Что-то иное?

Добавлено через 36 секунд
dev3214, вопрос-то ваш в чём?
1
5 / 5 / 0
Регистрация: 11.09.2021
Сообщений: 578
08.12.2023, 09:00
Цитата Сообщение от Элд Хасп Посмотреть сообщение
В какой момент?
Явно по клику на кнопке?
Автоматом при потере фокуса строкой?
Что-то иное?
Добавлено через 36 секунд
dev3214, вопрос-то ваш в чём?
Не заметил... Тут рассматривается DataGrid <- ObservableCollection (Изменили ObservableCollection, изменения отобразились в DataGrid).

Меня интересует DataGrid -> ObservableCollection-> БД (Изменили DataGrid изменения попали в ObservableCollection, изменения попали в БД)

Если не возражает, продолжу...

Вопрос: Как выполнить DataGrid -> ObservableCollection-> БД по следующей логике?

Логика внесения изменений в DataGrid пользователем:
- Пользователь установил фокус на ячейку DataGrid;
- Нажал F2;
- DataGrid перевело ячейку в режим редактирования;
- Пользователь внёс изменения;
- Нажал Ввод(или Tab);
- DataGrid вывело ячейку из режима редактирования.
- Приложение сохранило изменения в БД.



Вопрос-1.
Делать Model. Index и ViewModel. IndexViewModel?
Или делать только и ViewModel. IndexViewModel?

Model. Index (наверное это не нужно, раз делается IndexViewModel?)
C#
1
2
3
4
5
6
7
 [Table("Indexes")]
    public class Index : BaseInpc
    {
        public int Id { get; set; }
        public string Name { get; set; }        
       
    }
ViewModel. IndexViewModel
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 [Table("Indexes")]
    public class IndexViewModel : BaseInpc
    {
        public int Id { get; set; }
        
        private string name;
        public string Name { get => name;
            set
            {
                Set(ref name, value); 
                Debug.WriteLine($"Index prop -- Name {name}");
            }
        }
 
        protected override void OnPropertyChanged(string propertyName, object oldValue, object newValue)
        {
            base.OnPropertyChanged(propertyName, oldValue, newValue);
 
            Debug.WriteLine($"OnPropertyChanged--propertyName {propertyName}");
        }
 
    }


Вопрос-2.
В <DataGrid ItemsSource="{Binding Indexes}" ... > нужно прописывать ItemsSource="{Binding Indexes, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" ?

В <DataGridTextColumn Header="Имя" Binding="{Binding Name}" ... /> нужно прописывать Binding="{Binding Name, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" ?

XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<DataGrid Grid.Row="1"                                         
                     ItemsSource="{Binding Indexes}"
                    SelectedIndex="2"
                    AutoGenerateColumns="False"
                    CanUserAddRows="True"
                    GridLinesVisibility="Vertical"                                  
                    VerticalGridLinesBrush="DarkGray"
                     AlternatingRowBackground="LightGray"
                     >
            <DataGrid.Columns>
                <DataGridTextColumn Header="id" Binding="{Binding Id}" Width="Auto"/>
                <DataGridTextColumn Header="Имя" Binding="{Binding Name}" Width="*"/>
            </DataGrid.Columns>
        </DataGrid>
0
 Аватар для Andrey-MSK
3308 / 2196 / 386
Регистрация: 14.08.2018
Сообщений: 7,392
Записей в блоге: 4
08.12.2023, 09:20
Цитата Сообщение от dev3214 Посмотреть сообщение
Логика внесения изменений в DataGrid пользователем:
- Пользователь установил фокус на ячейку DataGrid;
- Нажал F2;
- DataGrid перевело ячейку в режим редактирования;
- Пользователь внёс изменения;
- Нажал Ввод(или Tab);
- DataGrid вывело ячейку из режима редактирования.
- Приложение сохранило изменения в БД.
А вот такое лучше не делать... Так как очень сложно сохранить целостность данных при таком подходе. Добавление/Изменение данных нужно делать модальными окнами или отдельными элементами UI по команде.
Вот примерно так это выглядит в UI

Под каждым DataGrid есть поля для редактирования и кнопка для записи данных.
1
 Аватар для Andrey-MSK
3308 / 2196 / 386
Регистрация: 14.08.2018
Сообщений: 7,392
Записей в блоге: 4
08.12.2023, 09:37
И DataGrid объявляется только для чтения.

Добавлено через 15 минут
dev3214, Ну если уже очень надо, то тут нужна связка IEditableObject, INPC, CollectionChangedEvent. Но лучше не заниматься таким...
1
5 / 5 / 0
Регистрация: 11.09.2021
Сообщений: 578
08.12.2023, 10:15
Цитата Сообщение от Andrey-MSK Посмотреть сообщение
сложно сохранить целостность данных при таком подходе
Если не сложно можно детальнее описать как это происходит?


Я нашёл такие решения:
Это всё как-то "прикрутить" не получится?

Решение: ObservableCollection
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public ItemsViewModel()
{
    Items.CollectionChanged += ItemsOnCollectionChanged;
}
 
private void ItemsOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    if (e.OldItems != null)
    {
        foreach (INotifyPropertyChanged item in e.OldItems)
            item.PropertyChanged -= UpdatePrice;
    }
    if (e.NewItems != null)
    {
        foreach (INotifyPropertyChanged item in e.NewItems)
            item.PropertyChanged += UpdatePrice;
    }
}
Решение: BindingList
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public ToDoListViewModel()
{    
    // Загрузка
      _todoDataList = _fileOService.LoadData();
      
    // Создание событие `_todoDataList_ListChanged`
    _todoDataList.ListChanged += _todoDataList_ListChanged;            
}        
 
private void _todoDataList_ListChanged(object sender, ListChangedEventArgs e)
{
    if (e.ListChangedType == ListChangedType.ItemAdded 
        || e.ListChangedType == ListChangedType.ItemDeleted 
        || e.ListChangedType == ListChangedType.ItemChanged)
    {
        try
        {
            _fileOService.SaveData(sender);
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
            // this.Close(); //  закрыть приложение
        }
    }
}

Решение: DataGrid-EventTrigger-RowEditEnding
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
<DataGrid x:Name="dataGrid" Margin="5,5,10,5" AutoGenerateColumns="False"  HorizontalAlignment="Stretch" ItemsSource="{Binding ProductList}" VerticalAlignment="Stretch" Height="566"  >
<i:Interaction.Triggers>
     <i:EventTrigger EventName="RowEditEnding" ">
        <cmd:EventToCommand Command="{Binding EndEdit}" PassEventArgsToCommand="True"/>
     </i:EventTrigger>
</i:Interaction.Triggers>
<DataGrid.Columns>
  <DataGridTextColumn x:Name="Id" Binding="{Binding Path=Id, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" Header="Id"/>
    <DataGridTextColumn x:Name="name" Binding="{Binding Path=Name, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" Header="Name"/>
    <DataGridTextColumn x:Name="cost" Binding="{Binding Path=Cost, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" Header="Cost"/>
    <DataGridTextColumn x:Name="Quantity" Binding="{Binding Path=Quantity, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" Header="Quantity"/>
    <DataGridTextColumn x:Name="total" Binding="{Binding Path=Total, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" Header="Total"/>
</DataGrid.Columns>
0
 Аватар для Andrey-MSK
3308 / 2196 / 386
Регистрация: 14.08.2018
Сообщений: 7,392
Записей в блоге: 4
08.12.2023, 10:40
Цитата Сообщение от dev3214 Посмотреть сообщение
Если не сложно можно детальнее описать как это происходит?
Ну я же вам написал
Цитата Сообщение от Andrey-MSK Посмотреть сообщение
то тут нужна связка IEditableObject, INPC, CollectionChangedEvent. Но лучше не заниматься таким...
Вам нужно хранить несколько состояний объекта - до редактирования, для отмены, и после, для записи. И вот во время этого всего есть большая вероятность напутать... Нужно делать валидацию на NULL, соответствие типов и т.д.
И ещё, БД это вам не Excel, тут редактирование ячеек абсолютно не подходит, тут оперируют полностью записью таблицы, а не отдельными её полями.
Вот смотрите, у вас запись из 25 полей - что вы будете делать чтобы работать с ней как с Excel (ваша хотелка с DataGrid)? Писать 25 запросов на изменение каждого поля? А если нужно поменять три? И после изменения каждого поля вы будете отправлять запрос в БД на UPDATE всей записи?

Добавлено через 3 минуты
dev3214, Потому повторю ещё раз
Цитата Сообщение от Andrey-MSK Посмотреть сообщение
Но лучше не заниматься таким...
1
5 / 5 / 0
Регистрация: 11.09.2021
Сообщений: 578
08.12.2023, 10:54
Цитата Сообщение от Andrey-MSK Посмотреть сообщение
Вам нужно хранить несколько состояний объекта - до редактирования, для отмены, и после, для записи. И вот во время этого всего есть большая вероятность напутать... Нужно делать валидацию на NULL, соответствие типов и т.д.
И ещё, БД это вам не Excel, тут редактирование ячеек абсолютно не подходит, тут оперируют полностью записью таблицы, а не отдельными её полями.
Вот смотрите, у вас запись из 25 полей - что вы будете делать чтобы работать с ней как с Excel (ваша хотелка с DataGrid)? Писать 25 запросов на изменение каждого поля? А если нужно поменять три? И после изменения каждого поля вы будете отправлять запрос в БД на UPDATE всей записи?
Понятно... Надо переварить...
Я думал:
- пользователь меняет ячейку;
- срабатывает событие коллекции;
- В событии коллекции делаем _dataContextApp.SaveChanges();
- EntityFramework отправляет изменения (делает запрос на обновление одной записи в таблице);
или
- срабатывает событие коллекции;
- получить всю запись ;
- сделать запрос на обновление одной записи в таблице UPDATE tovar SET price=500 WHERE id=5;
0
 Аватар для Andrey-MSK
3308 / 2196 / 386
Регистрация: 14.08.2018
Сообщений: 7,392
Записей в блоге: 4
08.12.2023, 11:19
Цитата Сообщение от dev3214 Посмотреть сообщение
- сделать запрос на обновление одной записи в таблице UPDATE tovar SET price=500 WHERE id=5;
Я вам не зря про 25 полей в одной записи написал.
Цитата Сообщение от dev3214 Посмотреть сообщение
- пользователь меняет ячейку;
- срабатывает событие коллекции;
- В событии коллекции делаем _dataContextApp.SaveChanges();
- EntityFramework отправляет изменения (делает запрос на обновление одной записи в таблице);
А если в таблице поля NOT NULL, что вы будете делать с неполной записью?

Добавлено через 5 минут
dev3214, А если для показа в DataGrid используются данные VIEW, которые основаны на данных нескольких таблиц? Довольно таки распространённая ситуация.
Так что мой вам совет - бросьте это и делайте как я показал на картинке выше, либо модальным окном. И это будет удобно, безопасно и, с точки зрения сохранности данных в БД, верно.

Добавлено через 6 минут
dev3214, И команда, в этом случае, будет выглядеть вот так
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
private async Task SaveDataAsync()
{
    try
    {
        // Создаём объект для записи из данных в элементах UI
        HBMachineLabor labor = new HBMachineLabor
        {
            MachineHBID = _machineLaborID,
            LaborWorkID = LaborHBWork.IDLaborWork,
            MachineTypeID = SelectedMachine.MachineTypeID,
            MachineType = SelectedMachine.MachineType,
            MachineHours = (decimal)MachineHours
        };
 
        // Если это редактирование
        if (_machineLaborID > 0)
        {
            // Получаем индекс редактируемого элемента
            int index = MachineLabors.IndexOf(SelectedMachineLabor);
 
            // Записываем данные в БД
            await _mainDA.LaborHBTypeDA.UpdateMachineLaborAsync(labor);
 
            // Получаем контекст View
            ViewContext.Send(vc =>
            {
                // Записываем отредактированный объект в коллекцию по старому индексу
                MachineLabors[index] = labor;
            }, null);
 
            // Ставим на него выделение
            SelectedMachineLabor = MachineLabors.FirstOrDefault(m => m.MachineHBID == labor.MachineHBID);
        }
        // Если запись новая
        else
        {
            // Записываем данные в БД
            await _mainDA.LaborHBTypeDA.AddMachineLaborAsync(labor);
 
            ViewContext.Send(vc =>
            {
                // Добавляем элемент в коллекцию
                MachineLabors.Add(labor);
            }, null);
 
            // Ставим на него выделение
            SelectedMachineLabor = MachineLabors.FirstOrDefault(m => m.MachineHBID == labor.MachineHBID);
        }
    }
    catch (Exception ex)
    {
        _windowService.ShowErrorMessage(ex.Message, "Ошибка");
    }
}
1
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16115 / 11236 / 2887
Регистрация: 21.04.2018
Сообщений: 33,037
Записей в блоге: 2
08.12.2023, 13:48
Цитата Сообщение от dev3214 Посмотреть сообщение
- DataGrid вывело ячейку из режима редактирования.
- Приложение сохранило изменения в БД.
Согласен с Andrey-MSK.
Это очень рискованный сценарий с точки зрения безопасности и целостности данных.
Имеет смысл только в том случае, если создаётся промежуточное хранение редактируемых данных. А итоговое сохранение в основные данные происходит после полного завершения редактирования сущности и верификации новых данных.
2
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
08.12.2023, 13:48
Помогаю со студенческими работами здесь

Изменение свойства при изменении другого свойства
Предположим у меня есть товар,у которого есть несколько размеров и к каждому размеру привязана цена.Как сделать,к примеру я выбираю размер...

Изменение свойства элемента в другой форме
Как изменить свойство элемента в другой форме? Например, на: Form2.button1.Enabled = false; пишет, что недоступен из-за его степени...

CSS: Изменение свойства другого элемента
Здравствуйте! Например, у меня есть 2 элемента. Я могу менять свойства одного объекта при наведении на другой (в :hover) используя CSS? Или...

Изменение свойства Background выбранного элемента в ListBox
Добрый день! Необходимо изменить цвет выбранного элемента в ListBox. Создаю триггер: &lt;Trigger Property=&quot;IsSelected&quot;...

Обновление ObservableCollection
Добрый день, Вопрос по WPF. Я создаю ObservableCollection: private ObservableCollection&lt;String&gt; citiesList = new...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
19
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru