Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / WPF, Silverlight Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2 3 4   вперед  Ctrl      все
 Отслеживание изменений в DataGrid  [new]
Eld Hasp
Member

Откуда:
Сообщений: 225
DataGrid, как я понял, предназначен для работы с БД и работает транзакциями. Поэтому не очень подходит для редактирования небольших списочных свойств. В инете много разных способов приспособления DataGrid для этих целей, но все они какие-то "корявые".
Поэтому и хотел поинтересоваться, более красивым логичным решением.
Приведу пример и объясню, что мне в нём не нравится.

Класс для элементов списка
  public  class FieldTwoProperty : OnPropertyChangedClass
    {
        private string _name;

        public string Name
        {
            get { return _name; }
            set { _name = value; OnPropertyChanged(); }
        }

        private string _value;

        public string Value
        {
            get { return _value; }
            set { _value = value; OnPropertyChanged(); }
        }

        public override bool Equals(object obj)
        {
            var property = obj as FieldTwoProperty;
            return property != null &&
                   _name == property._name &&
                   _value == property._value;
        }

        public override int GetHashCode()
        {
            var hashCode = 179903332;
            hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(_name);
            hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(_value);
            return hashCode;
        }
    }
Модель
    public class Model
    {
        List<FieldTwoProperty> _listField;
        public Model()
        {
            _listField = new List<FieldTwoProperty>()
            {
                new FieldTwoProperty(){Name="Телефон",Value= "+0 (123) 456-78-90"},
                new FieldTwoProperty(){Name="Адрес",Value= "Новые Васюки"}
            };
        }
        public IEnumerable<FieldTwoProperty> GetFields() => _listField.ConvertAll(field => new FieldTwoProperty() {Name=field.Name, Value=field.Value });
        public void SetFields(IEnumerable<FieldTwoProperty> value) => _listField = value?.ToList();
        public bool IsEqualsField(IEnumerable<FieldTwoProperty> value)
        {
            if (_listField == null && value == null) return true;
            if (_listField == null || value == null || _listField.Count != value.Count()) return false;
            return value
                .Select((field, ind) => new { Field = field, Index = ind })
                .FirstOrDefault(fieldInd => !fieldInd.Field.Equals(_listField[fieldInd.Index]))
                == null;
        }
    }
Модель представления
 public   class ViewModel : OnPropertyChangedClass
    {
        private List<FieldTwoProperty> _listFields;

        public List<FieldTwoProperty> ListFields
        {
            get { return _listFields; }
            set { _listFields = value; OnPropertyChanged(); }
        }

        private Model model;

        public ViewModel()
        {
            model = new Model();
            ListFields = model.GetFields().ToList();
        }

        private ICommand _saveComm;
        public ICommand SaveComm => _saveComm ?? (_saveComm = new RelayCommand(OnSave));
        private void OnSave(object value)
        {
            model.SetFields(value as List<FieldTwoProperty>);
            ListFields = model.GetFields().ToList();
        }

        public bool IsNotModified => model.IsEqualsField(_listFields);
        public bool IsModified => !IsNotModified;

        public void Changed() => OnPropertyChanged("IsNotModified IsModified");
    }
Окно
<Window x:Class="ChangedSourceInDatagrid.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:ChangedSourceInDatagrid"
        mc:Ignorable="d" SizeToContent="Height"
        Title="MainWindow" Width="300">
    <d:Window.DataContext>
        <local:ViewModel>
            <local:ViewModel.ListFields>
                <local:FieldTwoProperty Name="Поле 1" Value="Значение 1"/>
                <local:FieldTwoProperty Name="Поле 2" Value="Значение 2"/>
            </local:ViewModel.ListFields>
        </local:ViewModel>
    </d:Window.DataContext>
    <local:ContextHolder>
        <local:ContextHolder.Commands>
            <local:CommandBinding RoutedCommand="{x:Static ApplicationCommands.Save}"
                                  RelayCommand="{Binding SaveComm}"/>
        </local:ContextHolder.Commands>
        <StackPanel>
            <DataGrid x:Name="DG"  Margin="5" ItemsSource="{Binding ListFields, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" ColumnWidth="*" 
                      SelectedCellsChanged="DG_SelectedCellsChanged"
                      LostFocus="DG_LostFocus"/>
            <Button Margin="5" HorizontalAlignment="Center" IsEnabled="{Binding IsModified}" 
                    Command="{x:Static ApplicationCommands.Save}"
                    CommandParameter="{Binding ListFields}">Сохранить</Button>
        </StackPanel>
    </local:ContextHolder>
</Window>
Code Behind
    public partial class MainWindow : Window
    {
        private ViewModel viewModel=new ViewModel();
        public MainWindow()
        {
            InitializeComponent();
            DataContext = viewModel;
        }

        private void DG_SelectedCellsChanged(object sender, SelectedCellsChangedEventArgs e)
        {
            viewModel.Changed();
        }
        private void DG_LostFocus(object sender, RoutedEventArgs e)
        {
            viewModel.Changed();
        }
    }

Набор классов для работы с командами не прикладываю, он идентичен предоставленному Романом в https://www.sql.ru/forum/1304673/pravilnoe-razmeshhenie-funkcionala-i-privyazki-komand

Теперь что мне не нравится.
1) Использование обработчиков событий для отслеживания изменений в DataGrid. Вызов методов VM из CB.
2) Отсутствие у DataGrid события извещения о немедленном изменений значений в ячейке. В данном пример, это приводит к тому, что кнопка не активна до тех пор пока не выйдешь из первой изменённой ячейки. Если изменяешь только одну и надо сразу сохранить изменения, то так не получится. Т.е. более удобным здесь было бы событие аналогичное TextBox.TextChanged
3) Добавление новой строки только после выхода из редактирования предыдущей новой. Это приводит к тому, что когда ввёл значение в новую строку и пытаешься его сохранить кликнув по кнопке - кнопка отпрыгивает и надо переводить курсор и заново кликать по кнопке.

Вижу несколько вариантов решения:
- Изменить класс FieldTwoProperty добавив в него события извещения изменения элементов, создания нового элемента и потом прослушивать их.
- Создать кастомный вид коллекции для источника DataGrid
- Вместо DataGrid создать свой UserControl

Какие ещё могут быть варианты? Какое решение будет лучше соответствовать концепциям WPF, MVVM ?
6 ноя 18, 13:19    [21725158]     Ответить | Цитировать Сообщить модератору
 Re: Отслеживание изменений в DataGrid  [new]
Shocker.Pro
Member

Откуда: ->|<- :адуктО
Сообщений: 20286
Eld Hasp
1) Использование обработчиков событий для отслеживания изменений в DataGrid. Вызов методов VM из CB.
2) Отсутствие у DataGrid события извещения о немедленном изменений значений в ячейке.
Честно говоря, в твой код не вчитывался.
Я работал с DataGrid, где каждая строка привязана к VM строки, и мне не требовался CB, не очень понял, для чего он нужен.
Что касается уведомления об изменении текстбокса - делаешь свой CellEditTemplate в виде того же текстбокса и делаешь привязку к модели с немедленным уведомлением свойства (а не по потере фокуса).
6 ноя 18, 13:28    [21725171]     Ответить | Цитировать Сообщить модератору
 Re: Отслеживание изменений в DataGrid  [new]
Petro123
Member

Откуда: Загрузочный сектор Москвы (AutoPOI.ru)
Сообщений: 38458
Eld Hasp
соответствовать концепциям WPF, MVVM ?
не нужно пихать концепцию в грид.
Это слишком мелко.
Вы просто доводите компонент штатный до своих хотелок, либо берете готовый
https://docs.telerik.com/devtools/wpf/controls/radgridview/overview2
Компонент должен быть максимально изолирован от остального прикладного кода.
6 ноя 18, 13:39    [21725186]     Ответить | Цитировать Сообщить модератору
 Re: Отслеживание изменений в DataGrid  [new]
Petro123
Member

Откуда: Загрузочный сектор Москвы (AutoPOI.ru)
Сообщений: 38458
Eld Hasp
Поэтому не очень подходит для редактирования небольших списочных свойств.
они тоже в бд как справочники. Поэтому модель обычно другая.
6 ноя 18, 13:43    [21725195]     Ответить | Цитировать Сообщить модератору
 Re: Отслеживание изменений в DataGrid  [new]
Shocker.Pro
Member

Откуда: ->|<- :адуктО
Сообщений: 20286
Petro123
не нужно пихать концепцию в грид.
Как вариант. Я делал одну оболочку для него, это был именно юзерконтрол с СВ (из-за динамической загрузки столбцов, динамического назначения селекторов шаблонов) - но с точки зрения эксплуатации - да, концепция "черный ящик", а снаружи DP для встраивания в MVVM
6 ноя 18, 13:46    [21725204]     Ответить | Цитировать Сообщить модератору
 Re: Отслеживание изменений в DataGrid  [new]
Сон Веры Павловны
Member

Откуда:
Сообщений: 4710
Eld Hasp
предназначен для работы с БД и работает транзакциями.

Да ну, ерунда. Никаких транзакций там нет, и DataGrid вообще не в курсе, откуда пришли данные, и как сохраняются.
Eld Hasp
Теперь что мне не нравится.

Что мне не нравится сразу же и навскидку: Equals и GetHashCode зависят от значений изменяемых полей. На этом моменте можно долго и весело ловить разные баги (и да, я их ловил). Вышеупомянутые методы в связке должны идентифицировать объект (и балансировать дерево) вне зависимости от жизненного цикла объекта.
6 ноя 18, 13:47    [21725206]     Ответить | Цитировать Сообщить модератору
 Re: Отслеживание изменений в DataGrid  [new]
Petro123
Member

Откуда: Загрузочный сектор Москвы (AutoPOI.ru)
Сообщений: 38458
Сон Веры Павловны
Equals
да. С бд этого вообще не нужно.
6 ноя 18, 13:49    [21725214]     Ответить | Цитировать Сообщить модератору
 Re: Отслеживание изменений в DataGrid  [new]
Petro123
Member

Откуда: Загрузочный сектор Москвы (AutoPOI.ru)
Сообщений: 38458
Shocker.Pro
Petro123
не нужно пихать концепцию в грид.
Как вариант. Я делал одну оболочку для него, это был именно юзерконтрол с СВ (из-за динамической загрузки столбцов, динамического назначения селекторов шаблонов) - но с точки зрения эксплуатации - да, концепция "черный ящик", а снаружи DP для встраивания в MVVM
я помню. Но редко встречается, когда неизвестно сколько столбцов. У вас проект - динамика.
6 ноя 18, 13:50    [21725218]     Ответить | Цитировать Сообщить модератору
 Re: Отслеживание изменений в DataGrid  [new]
Petro123
Member

Откуда: Загрузочный сектор Москвы (AutoPOI.ru)
Сообщений: 38458
В субд и ОРМ однозначно идентифицирует объект PK.
6 ноя 18, 13:52    [21725220]     Ответить | Цитировать Сообщить модератору
 Re: Отслеживание изменений в DataGrid  [new]
Eld Hasp
Member

Откуда:
Сообщений: 225
Shocker.Pro
Eld Hasp
1) Использование обработчиков событий для отслеживания изменений в DataGrid. Вызов методов VM из CB.
2) Отсутствие у DataGrid события извещения о немедленном изменений значений в ячейке.
Честно говоря, в твой код не вчитывался.
Я работал с DataGrid, где каждая строка привязана к VM строки, и мне не требовался CB, не очень понял, для чего он нужен.
Что касается уведомления об изменении текстбокса - делаешь свой CellEditTemplate в виде того же текстбокса и делаешь привязку к модели с немедленным уведомлением свойства (а не по потере фокуса).
С TextBox в ячейке DataGrid пробовал. Там получаются проблемы с редактированием TetxBox - нужно два клика. Первым кликом выделяется ячейка, а вторым входишь в редактировании TextBox.
В новой строке, там по моему, вообще получалось три клика, и какие-то проблемы с добавлением в источник новой строки. Т.е. не получалось сравнить источник DG с источником в модели и определить, что изменения произошли.
Сон Веры Павловны
.... Да ну, ерунда. Никаких транзакций там нет, и DataGrid вообще не в курсе, откуда пришли данные, и как сохраняются.
Я может не правильно выразился. Я имел ввиду, конкретно, вот такой нюанс. Новая строка в DataGrid существует только в нём. В источнике её нет. Поэтому по источнику не получится определить были изменения или нет. В идеале, мне нужно получить такое поведение. При любом изменении в новой строке DG она сразу должна добавиться в источник. И, соответственно, в DG появится снизу другая новая строка.
Сон Веры Павловны
Что мне не нравится сразу же и навскидку: Equals и GetHashCode зависят от значений изменяемых полей...
В данном случае мне надо определить были ли внесены изменения в список, для этого мне надо сравнить список из DG и список в модели. Любое расхождение между списками: разное количество элементов, разная их последовательность, любое изменение в одном из свойств. Для последнего я и переопределил Equals. Если такой подход не верен, то как лучше сделать?
Petro123
не нужно пихать концепцию в грид.
Это слишком мелко.
Вы просто доводите компонент штатный до своих хотелок, либо берете готовый
https://docs.telerik.com/devtools/wpf/controls/radgridview/overview2
Компонент должен быть максимально изолирован от остального прикладного кода.
Под одной из концепцией я и имел ввиду "Компонент должен быть максимально изолирован от остального прикладного кода". Это одна из причин почему мне не нравится решение в моём примере.
radgridview - посмотрю, что за зверь. А как довести "компонент штатный до своих хотелок" - не знаю. То ли "хотелок" больше чем возможности штатного элемента, то ли мои возможности и умения значительно ниже моих "хотелок"
6 ноя 18, 14:28    [21725273]     Ответить | Цитировать Сообщить модератору
 Re: Отслеживание изменений в DataGrid  [new]
Petro123
Member

Откуда: Загрузочный сектор Москвы (AutoPOI.ru)
Сообщений: 38458
Eld Hasp,
Есть грид эксель, и есть грид для субд.
Тебе какой?
ЗЫ в дельфи это 2 разных грида.
6 ноя 18, 14:32    [21725278]     Ответить | Цитировать Сообщить модератору
 Re: Отслеживание изменений в DataGrid  [new]
Petro123
Member

Откуда: Загрузочный сектор Москвы (AutoPOI.ru)
Сообщений: 38458
Eld Hasp
разная их последовательность,
???
6 ноя 18, 14:35    [21725288]     Ответить | Цитировать Сообщить модератору
 Re: Отслеживание изменений в DataGrid  [new]
Shocker.Pro
Member

Откуда: ->|<- :адуктО
Сообщений: 20286
Eld Hasp
То ли "хотелок" больше чем возможности штатного элемента
Да. DataGrid вообще довольно слабый. Но хорошие гриды стоят денег, а бесплатные - г.
Так что либо платить деньги, либо пилить свой, с маджонгом и гейшами
6 ноя 18, 14:35    [21725290]     Ответить | Цитировать Сообщить модератору
 Re: Отслеживание изменений в DataGrid  [new]
Eld Hasp
Member

Откуда:
Сообщений: 225
Petro123
Eld Hasp,
Есть грид эксель, и есть грид для субд.
Тебе какой?
ЗЫ в дельфи это 2 разных грида.
DataDrid из C# + WPF + VS2017
6 ноя 18, 14:43    [21725300]     Ответить | Цитировать Сообщить модератору
 Re: Отслеживание изменений в DataGrid  [new]
Petro123
Member

Откуда: Загрузочный сектор Москвы (AutoPOI.ru)
Сообщений: 38458
Eld Hasp
то ли мои возможности

Третья причина в том что ты с базами на вы. А надо на ты.
Без них сложно.
6 ноя 18, 14:44    [21725301]     Ответить | Цитировать Сообщить модератору
 Re: Отслеживание изменений в DataGrid  [new]
Eld Hasp
Member

Откуда:
Сообщений: 225
Petro123
Eld Hasp
разная их последовательность,
???
Допустим, в DG поменяли местами первую и вторую строку. То есть элементы те же, но их последовательность другая.
6 ноя 18, 14:45    [21725305]     Ответить | Цитировать Сообщить модератору
 Re: Отслеживание изменений в DataGrid  [new]
Petro123
Member

Откуда: Загрузочный сектор Москвы (AutoPOI.ru)
Сообщений: 38458
Eld Hasp
DataDrid из C# + WPF + VS2017
я говорил о запросах. Какой нужен?.
Т.к. очередность в коллекции это странно.
6 ноя 18, 14:46    [21725306]     Ответить | Цитировать Сообщить модератору
 Re: Отслеживание изменений в DataGrid  [new]
Petro123
Member

Откуда: Загрузочный сектор Москвы (AutoPOI.ru)
Сообщений: 38458
Eld Hasp
Допустим, в DG поменяли местами первую и вторую строку. То есть элементы те же, но их последовательность другая.
жмакнули на сортировку?
6 ноя 18, 14:47    [21725309]     Ответить | Цитировать Сообщить модератору
 Re: Отслеживание изменений в DataGrid  [new]
Eld Hasp
Member

Откуда:
Сообщений: 225
Petro123
Eld Hasp
то ли мои возможности

Третья причина в том что ты с базами на вы. А надо на ты.
Без них сложно.
В данном случае в решении, вообще, нет БД. Небольшое приложение - данные из XML файла.
6 ноя 18, 14:47    [21725311]     Ответить | Цитировать Сообщить модератору
 Re: Отслеживание изменений в DataGrid  [new]
Petro123
Member

Откуда: Загрузочный сектор Москвы (AutoPOI.ru)
Сообщений: 38458
Eld Hasp
данные из XML файла.
а там имеет значение очередность?
6 ноя 18, 14:49    [21725315]     Ответить | Цитировать Сообщить модератору
 Re: Отслеживание изменений в DataGrid  [new]
Eld Hasp
Member

Откуда:
Сообщений: 225
Petro123
Eld Hasp
Допустим, в DG поменяли местами первую и вторую строку. То есть элементы те же, но их последовательность другая.
жмакнули на сортировку?
Ну в том числе. Или пользователю, захотелось какую-то строку переместить для своего удобства.
Так как данные в XML, то при любом изменении всё равно надо сохранять весь файл. Поэтому я просто определяю есть изменения или нет. Если есть, то всю инфу пересохраняю.
6 ноя 18, 14:50    [21725320]     Ответить | Цитировать Сообщить модератору
 Re: Отслеживание изменений в DataGrid  [new]
Eld Hasp
Member

Откуда:
Сообщений: 225
Petro123
Eld Hasp
данные из XML файла.
а там имеет значение очередность?
Только удобство для пользователя. Так как таких строк может или вообще не быть, или быть много. Они могут не помещаться все на видимом поле. И пользователь может передвинуть их вверх вниз в зависимости от того, что ему нужно видеть в первую очередь.
6 ноя 18, 14:53    [21725323]     Ответить | Цитировать Сообщить модератору
 Re: Отслеживание изменений в DataGrid  [new]
Petro123
Member

Откуда: Загрузочный сектор Москвы (AutoPOI.ru)
Сообщений: 38458
Eld Hasp,
Мрак.
Короче, ты жить богато и с зарплатой хочешь?
Тогда дальнейшее твое творчество уже наносит вред развитию программиста.
Выкинь xml и этот топик будет не нужен.
Удачи!
Имхо.
6 ноя 18, 14:53    [21725324]     Ответить | Цитировать Сообщить модератору
 Re: Отслеживание изменений в DataGrid  [new]
Eld Hasp
Member

Откуда:
Сообщений: 225
Shocker.Pro
Eld Hasp
То ли "хотелок" больше чем возможности штатного элемента
Да. DataGrid вообще довольно слабый. Но хорошие гриды стоят денег, а бесплатные - г.
Так что либо платить деньги, либо пилить свой, с маджонгом и гейшами

Пойду - пилить....
6 ноя 18, 14:55    [21725328]     Ответить | Цитировать Сообщить модератору
 Re: Отслеживание изменений в DataGrid  [new]
Petro123
Member

Откуда: Загрузочный сектор Москвы (AutoPOI.ru)
Сообщений: 38458
Eld Hasp
Они могут не помещаться все на видимом поле. И пользователь может передвинуть их вверх вниз в зависимости от того, что ему нужно видеть в первую очередь.
а) скроллинг б) доп. Колонка и свойство Очередность.
6 ноя 18, 14:56    [21725331]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2 3 4   вперед  Ctrl      все
Все форумы / WPF, Silverlight Ответить