Форум программистов, компьютерный форум, киберфорум
C#: WPF, UWP и Silverlight
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.55/47: Рейтинг темы: голосов - 47, средняя оценка - 4.55
3 / 2 / 1
Регистрация: 10.10.2015
Сообщений: 24
WPF

Загрузка данных из XML в DataGrid

26.11.2018, 12:31. Показов 9655. Ответов 33

Студворк — интернет-сервис помощи студентам
Всем привет.

У меня есть View, на котором есть DataGrid. В DataGrid должен подгружаться XML-файл по нажатию на кнопку "Загрузка XML".

Интересует вопрос как организовать отображение данных из XML в DataGrid. Понимаю, что надо использоваться ObservableCollection, но не знаю как написать это в DataGrid и реализовать в коде.

Также в модели присутствует функционал создания XML и добавления данных в XML, но думаю что он тут не играет какой-либо роли.
Код ДатаГрид
MainView.xaml
XML
1
2
3
4
5
6
7
8
9
10
<DataGrid ItemsSource="{Binding Path=ItemsOfGrid}" Style="{StaticResource AzureDataGrid}" AutoGenerateColumns="False" Margin="0,199,0,0">
            <DataGrid.Columns>
                <DataGridTextColumn Header="ФИО клиента" Binding="{Binding Path=UserFIOclass}" />
                <DataGridTextColumn Header="Дата рождения" Binding="{Binding Path=DateOfBirth}" />
                <DataGridTextColumn Header="Пол" Binding="{Binding Path=Male}" />
                <DataGridTextColumn Header="Место работы" Binding="{Binding Path=UserJobClass}" />
                <DataGridTextColumn Header="Доход" Binding="{Binding Path=Salary}" />
                <DataGridTextColumn Header="Телефон" Binding="{Binding Path=Phone}" />
            </DataGrid.Columns>
        </DataGrid>
ViewModel:
RootVM.cs
Кликните здесь для просмотра всего текста
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
Settings settings;
        private IDialogCoordinator _dialog;
        public RootVM()
        {
            _model.PropertyChanged += (s, e) => { RaisePropertyChanged(e.PropertyName); };            
            _dialog = DialogCoordinator.Instance;
 
            _currentContentVM = view;
            settings = new Settings();
        }
 
        private object _currentContentVM;
        public object CurrentContentVM
        {
            get
            {
                return _currentContentVM;
            }
 
            set
            {
                _currentContentVM = value;
                RaisePropertyChanged("CurrentContentVM");
            }
        }
        private ICommand _addFileCommand { get; set; }
        public ICommand AddFileCommand
        {
            get
            {
                return _addFileCommand ?? (_addFileCommand = new RelayCommand(() =>
                {
                    AddFileInGrid();
                }));
            }
        }
        public string FIO
        {
            get
            {
                return _model.UserFIO;
            }
            set
            {
                _model.UserFIO = value;
                RaisePropertyChanged("FIO");
            }
        }
        public DateTime DateOfBirth
        {
            get
            {
                return _model.UserDateOfBirth;
            }
            set
            {
                _model.UserDateOfBirth = value;
                RaisePropertyChanged("DateOfBirth");
            }
        }
        public string Male
        {
            get
            {
                return _model.UserMale;
            }
            set
            {
                _model.UserMale = value;
                RaisePropertyChanged("Male");
            }
        }
        public string Job
        {
            get
            {
                return _model.UserJob;
            }
            set
            {
                _model.UserJob = value;
                RaisePropertyChanged("Job");
            }
        }
        public string Salary
        {
            get
            {
                return _model.UserSalary;
            }
            set
            {
                _model.UserSalary = value;
                RaisePropertyChanged("Salary");
            }
        }
        public string Phone
        {
            get
            {
                return _model.UserPhone;
            }
            set
            {
                _model.UserPhone = value;
                RaisePropertyChanged("Phone");
            }
        }
        public bool FileLoad
        {
            get
            {
                return _model.IsUserFileLoad;
            }
            set
            {
                _model.IsUserFileLoad = value;
                RaisePropertyChanged("FileLoad");
            }
        }
        public string FileLoadPath
        {
            get
            {
                return _model.UserFileLoadPath;
                
            }
            set
            {
                _model.UserFileLoadPath = value;
                RaisePropertyChanged("FileLoadPath");                
            }
        }
        public IList<User> ItemsOfGrid
        {
            get
            {
                return _model.UserDataGrid;
            }
            set
            {
                _model.UserDataGrid = value;
                RaisePropertyChanged("ItemsOfGrid");
            }
        }
       
        private void AddFileInGrid()
        {
            FileLoadPath = _model.DocLoad();
        }
 
        private object view { get; set; } = new Views.MainView();
        internal MainModel _model { get; } = new MainModel();


Код Модели:
MainModel.cs
Кликните здесь для просмотра всего текста
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
private string _userFIO;
        private DateTime _userDateOfBirth;
        private string _userMale;
        private string _userJob;
        private string _userSalary;
        private string _userPhone;
        private bool _isUserFileLoad = false;
        private string _userFileLoadPath;
        private string _userFileName;
        private IList<User> _userDataGrid = new ObservableCollection<User>();
public MainModel()
        {
            UserWidthMain = _userWidthMain;
            UserHeightMain = _userHeightMain;
            UserFIO = _userFIO;
            UserDateOfBirth = _userDateOfBirth;
            UserMale = _userMale;
            UserJob = _userJob;
            UserSalary = _userSalary;
            UserPhone = _userPhone;
            IsUserFileLoad = _isUserFileLoad;
            UserFileLoadPath = _userFileLoadPath;
            UserDataGrid = _userDataGrid;
        }
public string UserFIO
        {
            get
            {
                return _userFIO;
            }
 
            set
            {
                _userFIO = value;
            }
        }
        public DateTime UserDateOfBirth
        {
            get
            {
                return _userDateOfBirth;
            }
 
            set
            {
                _userDateOfBirth = value;
            }
        }
        public string UserMale
        {
            get
            {
                return _userMale;
            }
 
            set
            {
                _userMale = value;
            }
        }
        public string UserJob
        {
            get
            {
                return _userJob;
            }
 
            set
            {
                _userJob = value;
            }
        }
        public string UserSalary
        {
            get
            {
                return _userSalary;
            }
 
            set
            {
                _userSalary = value;
            }
        }
        public string UserPhone
        {
            get
            {
                return _userPhone;
            }
 
            set
            {
                _userPhone = value;
            }
        }
        public bool IsUserFileLoad
        {
            get
            {
                return _isUserFileLoad;
            }
 
            set
            {
                _isUserFileLoad = value;
            }
        }
        public string UserFileLoadPath
        {
            get
            {
                return _userFileLoadPath;
            }
 
            set
            {
                _userFileLoadPath = value;
            }
        }
        public string UserFileName
        {
            get
            {
                return _userFileName;
            }
 
            set
            {
                _userFileName = value;
            }
        }
        public IList<User> UserDataGrid
        {
            get
            {
                return _userDataGrid;
            }
            set
            {
                _userDataGrid = value;
            }
        }
public string DocLoad()
        {
            OpenFileDialog f_dialog = new OpenFileDialog();
            f_dialog.Filter = "Xml-файлы (*.xml)|*.xml|Все файлы (*.*)|*.*";
            if (f_dialog.ShowDialog() == true)
            {
                _isUserFileLoad = true;
                return Path.GetDirectoryName(f_dialog.FileName + "\\" + _userFileName);//Запоминаем директорию открытого файла
            }
            return null;
        }


Код XML:
XML
1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="utf-8"?>
<Clients>
  <Client>
    <Name>gdfgdg</Name>
    <Date_Of_Birth>2010-01-04</Date_Of_Birth>
    <Sex>Мужской</Sex>
    <Job>dfgdg</Job>
    <Salary>324234</Salary>
    <Telephone>4234</Telephone>
  </Client>
</Clients>
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
26.11.2018, 12:31
Ответы с готовыми решениями:

Загрузка данных из XML в DataGrid
Доброго времени суток. Есть датагрид с тремя столбцами: 1) Текстовый &quot;Имя&quot;; 2) combo со списком возможных состояний 3) Текстовый...

Загрузка и сохранение DataGrid, xml
Доброго времени суток, форумчане. Столкнулся с проблемой - полез на форумы. Почитал но так и не понял как осуществить загрузку DataGrid...

Чтение их xml опреденных пунктов и загрузка в datagrid
Добрый день. Вообщем существует такой хмл. &lt;СчетаПК ДатаФормирования=&quot;2009-07-07&quot; НомерДоговора=&quot;1020&quot;...

33
управление сложностью
 Аватар для Почтальон
1693 / 1306 / 259
Регистрация: 22.03.2015
Сообщений: 7,545
Записей в блоге: 5
29.11.2018, 07:59
Студворк — интернет-сервис помощи студентам
Ребята, позвольте вмешаться, пока не поздно
Если хотите делать все по феншую, то логичнее сделать абстрактный класс с необходимыми методами, и уже наследоваться в реализации от него, иначе сегодня нужен xml, завтра json и т.п. (это я к нижеследующему)
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Ни каких свойств в модели не будет. В модели будут только методы.
Это сугубо личное мнение
0
3 / 2 / 1
Регистрация: 10.10.2015
Сообщений: 24
29.11.2018, 11:20  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Посмотрите, что получилось. Всё понятно? Есть вопросы - задавайте.
То есть при выделении строки в DataGrid у нас должны подгружаться данные в верхний грид. Для этого там установлено DataContext и привязано свойство CurrentClient, который будет содержать выделенного клиента?
Цитата Сообщение от Элд Хасп Посмотреть сообщение
По View у меня ещё вопросы.
Начали создавать новую запись. Ввели данные. Но теперь нужна кнопки "Сохранить изменения" и "Выйти".
Остальные кнопки надо скрыть на это время.
Так же надо различать режимы редактирования и добавления данных.
Подумайте как это всё прописать в View и ViewModelDesigned. Какие нужны дополнительные свойства, методы, команды.
То есть предполагается, что сначала нажимается кнопка "Добавить", далее заполняются текстбоксы, после чего нажимается кнопка "Сохранить изменения" и данные сохраняются в DataGrid? Если так, то:
Предполагается, что на форме есть еще две кнопки "Сохранить изменения" и "Выйти".
Тогда к StackPanel, содержащие кнопки "Добавить", "Редактировать", "Сохранить", "Сохранить в...", "Открыть XMl-файл" и кнопке "Удалить" к свойству Visibility прибиндить свойство Visible. К StackPanel с кнопками "Сохранить изменения" и "Выйти" прибиндить свойство VisibleSave:
Изменившийся XAML:
XML
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
<Grid Grid.Row="1">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition />
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition />
                <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>
            <StackPanel Orientation="Horizontal" 
                        HorizontalAlignment="Center" VerticalAlignment="Center"
                        Visibility="{Binding Visible}">
                <Button Visibility="{Binding IsEdit}" Content="Добавить" Command="{Binding AddCommand}" />
                <Button Content="Редактировать" Command="{Binding EditCommand}" CommandParameter="{Binding SelectedClient}"/>
            </StackPanel>
            <StackPanel Orientation="Horizontal" Grid.Column="2"
                        HorizontalAlignment="Center" VerticalAlignment="Center"
                        Visibility="{Binding Visible}">
                <Button Content="Сохранить" Command="{Binding SaveCommand}" />
                <Button Content="Сохранить в..." Command="{Binding SaveAsCommand}" />
                <Button Content="Открыть XML-файл" Command="{Binding OpenFileCommand}"/>
            </StackPanel>
            <StackPanel Orientation="Horizontal" Grid.Column="2" Visibility="{Binding VisibleSave}">
                <Button Content="Сохранить изменения" Command="{Binding SaveChange}"/>
                <Button Content="Выйти" Command="{Binding Exit}" />
            </StackPanel>
            <Button Content="Удалить" Grid.Column="4" VerticalAlignment="Center" HorizontalAlignment="Center" 
                    Command="{Binding RemoveCommand}" CommandParameter="{Binding SelectedClient}" 
                    Visibility="{Binding Visible}"/>
        </Grid>
Свойства Visible:
C#
1
2
public Visibility Visible { get; set; } = Visibility.Visible;
public Visibility VisibleSave { get; set; } = Visibility.Hidden;
При нажатии на кнопку "Добавить" свойство Visible должно принимать значение Visibility.Hidden, а свойство VisibleSave значение Visibility.Visible. Для этого был создан метод ChangeMode() для переключения между режимами добавления/сохранения:
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
public virtual void ChangeMode()
        {
            if (Visible == Visibility.Visible)
            {
                Visible = Visibility.Hidden;
                VisibleSave = Visibility.Visible;
            }
            else
            {
                Visible = Visibility.Visible;
                VisibleSave = Visibility.Hidden;
            }
        }
        private ICommand _saveChangeCommand { get; set; }
        public ICommand SaveChangeCommand => _saveChangeCommand ?? (_saveChangeCommand = new RelayCommand(OnSaveChange));
        protected virtual void OnSaveChange(object value)
        {
            //Сохранение данных
 
            //Метод смены режима
            ChangeMode();
        }
 
        private ICommand _exitModeCommand { get; set; }
        public ICommand ExitModeCommand => _exitModeCommand ?? (_exitModeCommand = new RelayCommand(OnExitMode));
        protected virtual void OnExitMode(object value)
        {
            ChangeMode();
        }
Код в VM написал для наглядности.
На счет различия режима добавления/редактирования:
Создать свойство в VM и Enum:
C#
1
2
3
4
5
6
7
public Mode IsChange { get; set; };
        public enum Mode
        {
            Нормальный = 1,
            Добавление = 2,
            Редактирование = 3
        }
При добавлении и редактировании свойство должно устанавливаться в определенное значение. Как-то так.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16152 / 11273 / 2890
Регистрация: 21.04.2018
Сообщений: 33,147
Записей в блоге: 2
29.11.2018, 11:21
Цитата Сообщение от Почтальон Посмотреть сообщение
Ребята, позвольте вмешаться, пока не поздно
Если хотите делать все по феншую, то логичнее сделать абстрактный класс с необходимыми методами, и уже наследоваться в реализации от него, иначе сегодня нужен xml, завтра json и т.п. (это я к нижеследующему)
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Ни каких свойств в модели не будет. В модели будут только методы.
Это сугубо личное мнение
Я начал делать такую реализацию, для того чтобы можно было наглядно объяснить RussianVodkaL как всё взаимодействует в MVVM. Ограничил Модель только методами, чтобы не было соблазна "сквозного" биндинга к свойствам Модели. ТС в начальной реализации так и делал, но из-за недопонимания функционирования, совершил многочисленные ошибки. В случае же с методами придётся явно в VM получать данные из модели и устанавливать значения свойств для привязки.
Абстрактный класс - мне, кажется, пока нового и сложностей для RussianVodkaL и так хватает.
0
управление сложностью
 Аватар для Почтальон
1693 / 1306 / 259
Регистрация: 22.03.2015
Сообщений: 7,545
Записей в блоге: 5
29.11.2018, 11:28
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Абстрактный класс - мне, кажется, пока нового и сложностей для RussianVodkaL и так хватает.
за-то сразу позволяет разделить "связь по слоям"
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16152 / 11273 / 2890
Регистрация: 21.04.2018
Сообщений: 33,147
Записей в блоге: 2
29.11.2018, 11:37
Цитата Сообщение от RussianVodkaL Посмотреть сообщение
о есть при выделении строки в DataGrid у нас должны подгружаться данные в верхний грид. Для этого там установлено DataContext и привязано свойство CurrentClient, который будет содержать выделенного клиента?
Не совсем. У нас выделенная строка привязана к SelectedClient. А CurrentClient будет иметь двоякое назначение. Если окно не находится в режиме редактирования, то оно связано с SelectedClient. Если окно в режиме редактирования, то там будет дубль выделенного клиента или поля для нового клиента. Это для того чтобы была возможность отмены редактирования. Эта логика буде в VM.
Цитата Сообщение от RussianVodkaL Посмотреть сообщение
То есть предполагается, что сначала нажимается кнопка "Добавить", далее заполняются текстбоксы, после чего нажимается кнопка "Сохранить изменения" и данные сохраняются в DataGrid? Если так, то:
Предполагается, что на форме есть еще две кнопки "Сохранить изменения" и "Выйти".
Тогда к StackPanel, содержащие кнопки "Добавить", "Редактировать", "Сохранить", "Сохранить в...", "Открыть XMl-файл" и кнопке "Удалить" к свойству Visibility прибиндить свойство Visible. К StackPanel с кнопками "Сохранить изменения" и "Выйти" прибиндить свойство VisibleSave:
Да, мысль правильная.
Чуть позже скину пример реализации.
Но из собственного опыта, лучше сделать другую реализацию. Нам понадобятся в VM флаги режима редактирования, создания нового клиента и наличия изменений. Флаги будут булевы и, как мне порекомендовали в своё время, начинаться с "Is...". Для привязки булевых свойств к свойству Visiblity нужно использовать либо триггеры, либо конвертеры. Сделаем с помощью конвертеров - чтобы не загружать XAML (пока Вам и так сложностей хватает)

Добавлено через 2 минуты
Цитата Сообщение от Почтальон Посмотреть сообщение
за-то сразу позволяет разделить "связь по слоям"
Давайте подключитесь. Пока всё на начальном этапе.
0
управление сложностью
 Аватар для Почтальон
1693 / 1306 / 259
Регистрация: 22.03.2015
Сообщений: 7,545
Записей в блоге: 5
29.11.2018, 11:38
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Пока всё на начальном этапе.
не-не-не, я только высказал свои мысли
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16152 / 11273 / 2890
Регистрация: 21.04.2018
Сообщений: 33,147
Записей в блоге: 2
29.11.2018, 15:19
Мы уже подошли к установлению взаимосвязей внутри View. Теперь нам без интерфейса INPC не обойтись. Я использую свой базовый класс для реализации интерфейса
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
    /// <summary>Базовый класс с реализацией INPC </summary>
    public class OnPropertyChangedClass : INotifyPropertyChanged
    {
        #region Событие PropertyChanged и метод для его вызова
        /// <summary>Событие для извещения об изменения свойства</summary>
        public event PropertyChangedEventHandler PropertyChanged;
        /// <summary>Метод для вызова события извещения об изменении свойства</summary>
        /// <param name="prop">Изменившееся свойство</param>
        public void OnPropertyChanged([CallerMemberName]string prop = "")
        {
            string[] names = prop.Split("\\/\r \n()\"\'-".ToArray(), StringSplitOptions.RemoveEmptyEntries);
            switch (names.Length)
            {
                case 0: break;
                case 1:
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop));
                    break;
                default:
                    OnPropertyChanged(names);
                    break;
            }
 
        }
 
        /// <summary>Метод для вызова события извещения об изменении списка свойств</summary>
        /// <param name="propList">Список имён свойств</param>
        public void OnPropertyChanged(IEnumerable<string> propList)
        {
            foreach (string prop in propList.Where(name => !string.IsNullOrWhiteSpace(name)))
                OnPropertyChanged(prop);
        }
 
        /// <summary>Метод для вызова события извещения об изменении списка свойств</summary>
        /// <param name="propList">Список свойств</param>
        public void OnPropertyChanged(IEnumerable<PropertyInfo> propList)
        {
            foreach (PropertyInfo prop in propList)
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop.Name));
        }
 
        /// <summary>Метод для вызова события извещения об изменении всех свойств</summary>
        /// <param name="propList">Список свойств</param>
        public void OnAllPropertyChanged()
            => OnPropertyChanged(GetType().GetProperties());
        #endregion
    }
}
Теперь надо установить наследование VM от этого класса и прописать в свойствах VM поддержку INPC. Таже можно часть методов VM, для которых не нужно взаимодействие с моделью, тоже прописать.
В результате наша VM выглядит так
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
    /// <summary>Класс ViewModel времени разработки</summary>
    public class ViewModelDesigned : OnPropertyChangedClass
    {
        #region Приватные поля для хранения значений свойсвт
        private Client _currentClient = new Client();
        private Client _selectedClient = new Client();
        private List<Client> _clients = new List<Client>();
        private bool _isEdit;
        private bool _isAddNew;
        private bool _isModified;
        #endregion
 
        #region Свойства для привязки
        /// <summary>Клиент чьи свойства редактируются</summary>
        public Client CurrentClient { get => _currentClient; set { _currentClient = value; OnPropertyChanged(); } }
        /// <summary>Клиент выделенный в DataGrid</summary>
        public Client SelectedClient { get => _selectedClient; set { _selectedClient = value; if (!IsEdit) CurrentClient = SelectedClient; OnPropertyChanged(); } }
        /// <summary>Список клиентов</summary>
        public virtual List<Client> Clients { get => _clients; set { _clients = value; OnPropertyChanged(); } }
 
        /// <summary>Флаг режима редактирования</summary>
        public bool IsEdit { get => _isEdit; set { _isEdit = value; OnPropertyChanged(); } }
        /// <summary>Флаг режима вдобавления нового клиета</summary>
        public bool IsAddNew { get => _isAddNew; set { _isAddNew = value; OnPropertyChanged(); } }
        /// <summary>Флаг наличия несохранённых изменений</summary>
        public bool IsModified { get => _isModified; set { _isModified = value; OnPropertyChanged(); } }
        #endregion
 
        #region Свойства, поля и методы для привязки команд
        /// <summary>Поле для хранения значения свойства OpenFileCommand</summary>
        private ICommand _openFileCommand { get; set; }
        /// <summary>Свойство для привязки команды Открыть Файл</summary>
        public ICommand OpenFileCommand => _openFileCommand ?? (_openFileCommand = new RelayCommand(OnOpenFile));
        /// <summary>Метод для команды OpenFileCommand</summary>
        protected virtual void OnOpenFile(object value) { }
 
        /// <summary>Поле для хранения значения свойства SaveCommand</summary>
        private ICommand _saveCommand { get; set; }
        /// <summary>Свойство для привязки команды Сохранить</summary>
        public ICommand SaveCommand => _saveCommand ?? (_saveCommand = new RelayCommand(OnSave));
        /// <summary>Метод для команды SaveCommand</summary>
        protected virtual void OnSave(object value) { }
 
        /// <summary>Поле для хранения значения свойства SaveAsCommand</summary>
        private ICommand _saveAsCommand { get; set; }
        /// <summary>Свойство для привязки команды Сохранить в....</summary>
        public ICommand SaveAsCommand => _saveAsCommand ?? (_saveAsCommand = new RelayCommand(OnSaveAs));
        /// <summary>Метод для команды SaveAsCommand</summary>
        protected virtual void OnSaveAs(object value) { }
 
        /// <summary>Поле для хранения значения свойства AddCommand</summary>
        private ICommand _addCommand { get; set; }
        /// <summary>Свойство для привязки команды Добавить</summary>
        public ICommand AddCommand => _addCommand ?? (_addCommand = new RelayCommand(OnAdd));
        /// <summary>Метод для команды AddCommand</summary>
        protected virtual void OnAdd(object value) { IsEdit = true; IsAddNew = true; CurrentClient = new Client(); }
 
        /// <summary>Поле для хранения значения свойства RemoveCommand</summary>
        private ICommand _removeCommand { get; set; }
        /// <summary>Свойство для привязки команды Удалить</summary>
        public ICommand RemoveCommand => _removeCommand ?? (_removeCommand = new RelayCommand(OnRemove));
        /// <summary>Метод для команды RemoveCommand</summary>
        protected virtual void OnRemove(object value) { }
 
        /// <summary>Поле для хранения значения свойства EditCommand</summary>
        private ICommand _editCommand { get; set; }
        /// <summary>Свойство для привязки команды Редактировать</summary>
        public ICommand EditCommand => _editCommand ?? (_editCommand = new RelayCommand(OnEdit));
        /// <summary>Метод для команды EditCommand</summary>
        protected virtual void OnEdit(object value) { IsEdit = true; CurrentClient = SelectedClient.Copy(); }
 
        /// <summary>Поле для хранения значения свойства RemoveCommand</summary>
        private ICommand _saveChangeCommand { get; set; }
        /// <summary>Свойство для привязки команды Удалить</summary>
        public ICommand SaveChangeCommand => _saveChangeCommand ?? (_saveChangeCommand = new RelayCommand(OnSaveChange));
        /// <summary>Метод для команды RemoveCommand</summary>
        protected virtual void OnSaveChange(object value) { }
 
        /// <summary>Поле для хранения значения свойства EditCommand</summary>
        private ICommand _exitCommand { get; set; }
        /// <summary>Свойство для привязки команды Редактировать</summary>
        public ICommand ExitCommand => _exitCommand ?? (_exitCommand = new RelayCommand(OnExit));
        /// <summary>Метод для команды EditCommand</summary>
        protected virtual void OnExit(object value)
        {
            // Проверка были изменения или нет
            if
            (
                IsEdit
                && ((IsAddNew && !CurrentClient.Equals(new Client()))
                    || (!IsAddNew && !CurrentClient.Equals(SelectedClient)))
            ) // Если были изменения, то вывод предупреждения
                if (MessageBox.Show("Данные не были сохранены!\nПри выходе изменения будут утеряны\nВсё равно выйти?", "Предупреждение!", MessageBoxButton.YesNo)
                     == MessageBoxResult.No)
                    return;
            IsEdit = false;
            IsAddNew = false;
            CurrentClient = SelectedClient;
        }
        #endregion
    }
Для конвертации значений в XAML нам нужны конвертеры. Пока нужен один, но я на всякий случай прописал два.
Первый - конвертация bool в Visibility. Сделал свой, а не использую системный. В своём предусмотрел возможность инвертирования через параметр.
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
    /// <summary>Конвертер преобразующий bool в Visibility</summary>
    [ValueConversion(typeof(Boolean), typeof(Visibility))]
    public class BooleanToVisibilityConverter : IValueConverter
    {
        /// <summary>Прямая конвертация bool в Visibility</summary>
        /// <param name="value">Значение для конвертации</param>
        /// <param name="targetType">Целевой тип</param>
        /// <param name="parameter">Параметр. Если в нём "not", "no", "false" или "нет", то инвертируем видимость</param>
        /// <param name="culture">Не используется</param>
        /// <returns>Видимость</returns>
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            Visibility ret = Visibility.Visible;
 
            // Если проверяемое значение не null и равно false, то коллапс
            if (value != null && ((value.GetType() == typeof(bool) && (bool)value == false)
                                    || (value.GetType() == typeof(string) && ((string)value).ToLower().Contains("false"))
                                  )
               )
                ret = Visibility.Collapsed;
 
            // Если параметр не null, то проверяем его тип
            if (parameter != null)
            {
                // Если тип параметра bool и он равен false, то инвертируем видимость
                if (parameter.GetType() == typeof(bool) && (bool)parameter == false)
                    if (ret == Visibility.Collapsed)
                        ret = Visibility.Visible;
                    else ret = Visibility.Collapsed;
 
                // Если тип параметра string и он содержит "not", "no", "false" или "нет", то инвертируем видимость
 
                if (parameter.GetType() == typeof(string)
                    && !string.IsNullOrWhiteSpace("not no false нет".Split().FirstOrDefault(str => ((string)parameter).ToLower().Contains(str))))
                    if (ret == Visibility.Collapsed)
                        ret = Visibility.Visible;
                    else ret = Visibility.Collapsed;
            }
 
            return ret;
        }
        /// <summary>Обратная конвертация не реализована</summary>
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return value;
        }
 
    }
И конвертер инверсии bool
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
    /// <summary>Конвертер инвертирующий bool</summary>
    [ValueConversion(typeof(Boolean), typeof(Boolean))]
    public class BooleanNotConverter : IValueConverter
    {
        /// <summary>Ивертация bool</summary>
        /// <param name="value">Инвертируемое значение</param>
        /// <param name="targetType">Не используется</param>
        /// <param name="parameter">Не используется</param>
        /// <param name="culture">Не используется</param>
        /// <returns>Инвертированное значение</returns>
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value.GetType() == typeof(bool))
                return !(bool)value;
            else
                return value;
        }
 
        /// <summary>Обратный конвертер</summary>
        /// <param name="value">Инвертируемое значение</param>
        /// <param name="targetType">Не используется</param>
        /// <param name="parameter">Не используется</param>
        /// <param name="culture">Не используется</param>
        /// <returns>Инвертированное значение</returns>
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value.GetType() == typeof(bool))
                return !(bool)value;
            else
                return value;
        }
    }
Добавил в словарь объявление конвертеров
XML
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
    <local:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
    <local:BooleanNotConverter x:Key="BooleanNotConverter"/>
    <Style TargetType="FrameworkElement" x:Key="BaseStyle">
        <Setter Property="Margin" Value="5"/>
        <Setter Property="TextElement.FontSize" Value="14"/>
        <Setter Property="Control.Padding" Value="5"/>
    </Style>
    <Style TargetType="TextBox" BasedOn="{StaticResource BaseStyle}"/>
    <Style TargetType="Button" BasedOn="{StaticResource BaseStyle}"/>
    <Style TargetType="TextBlock" BasedOn="{StaticResource BaseStyle}"/>
    <Style TargetType="ComboBox" BasedOn="{StaticResource BaseStyle}"/>
    <Style TargetType="DataGrid" BasedOn="{StaticResource BaseStyle}"/>
    <Style TargetType="DatePicker" BasedOn="{StaticResource BaseStyle}"/>
    <Style TargetType="Grid" BasedOn="{StaticResource BaseStyle}"/>
    <local:ViewModelDesigned x:Key="DesignedVM"
                             IsEdit="False" >
        <local:ViewModelDesigned.CurrentClient >
            <local:Client Name="Семён Семёныч" 
                          DateOfBirth="01.01.2010" 
                          Job="Школа" 
                          Salary="10 Snikers" 
                          Sex="Мужской" 
                          Telephone="Андроид" />
        </local:ViewModelDesigned.CurrentClient>
        <local:ViewModelDesigned.Clients>
            <local:Client Name="Семён Семёныч" 
                          DateOfBirth="01.01.2010" 
                          Job="Школа" 
                          Salary="10 Snikers" 
                          Sex="Мужской" 
                          Telephone="Андроид" />
            <local:Client Name="Иванов Иван Иваныч" 
                          DateOfBirth="01.01.2010" 
                          Job="Бездельник" 
                          Salary="Иждевенец" 
                          Sex="Мужской" 
                          Telephone="+1234567890" />
        </local:ViewModelDesigned.Clients>
    </local:ViewModelDesigned>
В View добавил новые кнопки, их привязку, установил привязку свойств IsEnabled для элементов редактирования, добавил DataContext для режима выполнения. Теперь можно запустить и посмотреть как работает View. Из кнопок в ней работают Добавить, Редактировать, Выйти.
XML
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="ViewDictionary.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>
    <Window.DataContext>
        <Binding Source="{StaticResource DesignedVM}"/>
    </Window.DataContext>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition />
        </Grid.RowDefinitions>
        <Grid DataContext="{Binding CurrentClient}">
            <Grid.RowDefinitions>
                <RowDefinition/>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="3*"/>
                <ColumnDefinition/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>
            <StackPanel>
                <TextBlock Text="ФИО Клиента"/>
                <TextBox Text="{Binding Name}" IsEnabled="{Binding DataContext.IsEdit, ElementName=window}"/>
            </StackPanel>
            <StackPanel Grid.Row="1">
                <TextBlock Text="Место работы"/>
                <TextBox  Text="{Binding Job}" IsEnabled="{Binding DataContext.IsEdit, ElementName=window}"/>
            </StackPanel>
 
            <StackPanel Grid.Column="1">
                <TextBlock Text="Дата рождения"/>
                <DatePicker SelectedDate="{Binding DateOfBirth}"  DisplayDate="2001-01-01" DisplayDateStart="1900-01-01"  IsEnabled="{Binding DataContext.IsEdit, ElementName=window}"/>
            </StackPanel>
            <StackPanel Grid.Column="1" Grid.Row="1">
                <TextBlock Text="Уровень дохода"/>
                <TextBox Text="{Binding Salary}" IsEnabled="{Binding DataContext.IsEdit, ElementName=window}"/>
            </StackPanel>
            <StackPanel Grid.Column="2">
                <TextBlock Text="Пол"/>
                <ComboBox SelectedItem="{Binding Sex}" ItemsSource="{Binding ListSex}" IsEnabled="{Binding DataContext.IsEdit, ElementName=window}"/>
            </StackPanel>
            <StackPanel Grid.Column="2" Grid.Row="1">
                <TextBlock Text="Телефон"/>
                <TextBox Text="{Binding Telephone}" IsEnabled="{Binding DataContext.IsEdit, ElementName=window}"/>
            </StackPanel>
        </Grid>
        <Grid Grid.Row="1" Visibility="{Binding IsEdit, ConverterParameter=not, Converter={StaticResource BooleanToVisibilityConverter}}">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition />
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition />
                <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>
            <StackPanel Orientation="Horizontal" 
                        HorizontalAlignment="Center" VerticalAlignment="Center">
                <Button Content="Добавить" Command="{Binding AddCommand}" />
                <Button Content="Редактировать" Command="{Binding EditCommand}" CommandParameter="{Binding SelectedClient}"/>
            </StackPanel>
            <StackPanel Orientation="Horizontal" Grid.Column="2"
                        HorizontalAlignment="Center" VerticalAlignment="Center">
                <Button Content="Сохранить" Command="{Binding SaveCommand}" />
                <Button Content="Сохранить в..." Command="{Binding SaveAsCommand}" />
                <Button Content="Открыть XML-файл" Command="{Binding OpenFileCommand}"/>
            </StackPanel>
            <Button Content="Удалить" Grid.Column="4" VerticalAlignment="Center" HorizontalAlignment="Center" Command="{Binding RemoveCommand}" CommandParameter="{Binding SelectedClient}"/>
        </Grid>
        <Grid  Grid.Row="1" Visibility="{Binding IsEdit, Converter={StaticResource BooleanToVisibilityConverter}}">
            <Grid.ColumnDefinitions>
                <ColumnDefinition/>
                <ColumnDefinition/>
                <ColumnDefinition Width="2*"/>
            </Grid.ColumnDefinitions>
            <Button Content="Сохранить изменения" Command="{Binding SaveChangeCommand}"/>
            <Button Grid.Column="1" Content="Выйти" Command="{Binding ExitCommand}" />
        </Grid>
        <DataGrid Grid.Row="2" ItemsSource="{Binding Clients}" 
                  AutoGenerateColumns="False" IsReadOnly="True" 
                  HeadersVisibility="Column"
                  SelectedItem="{Binding SelectedClient}">
            <DataGrid.Columns>
                <DataGridTextColumn Header="ФИО клиента" Binding="{Binding Name}" Width="4*"/>
                <DataGridTextColumn Header="Дата рождения" Binding="{Binding DateOfBirth, StringFormat=dd.MM.yyyyг.}" Width="2*" />
                <DataGridTextColumn Header="Пол" Binding="{Binding Sex}"  Width="2*"/>
                <DataGridTextColumn Header="Место работы" Binding="{Binding Job}"  Width="2*"/>
                <DataGridTextColumn Header="Доход" Binding="{Binding Salary}"  Width="2*"/>
                <DataGridTextColumn Header="Телефон" Binding="{Binding Telephone}" Width="2*"/>
            </DataGrid.Columns>
        </DataGrid>
 
    </Grid>
Запустите - посмотрите как работает. Если всё устраивает, будем переходит к VM времени исполнения для связи с Моделью.

Добавлено через 2 минуты
Цитата Сообщение от Почтальон Посмотреть сообщение
не-не-не, я только высказал свои мысли
У Вас-то опыта побольше. Я C# начал изучать чуть более 4-х месяцев назад. Абстрактные классы - знаю что такое, но пока не использовал. Учить тому чего сам твёрдо не знаю.... Поэтому пока так.

Добавлено через 6 минут
RussianVodkaL, обратите внимание на строчку в словаре
XML
20
                            IsEdit="False" >
У нас в View видна только одна коллекция кнопок. А нам надо смотреть обе коллекции, чтобы видеть как меняется View.
Устанавливая в этой строке "True" мы можем смотреть как выглядит наша View в режиме редактирования. Вот для этого, в том числе, и нужен DataContext времени разработки.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16152 / 11273 / 2890
Регистрация: 21.04.2018
Сообщений: 33,147
Записей в блоге: 2
29.11.2018, 15:23
Забыл написать - для проверки на равенство значений добавил в Client переопределение Equals и GetHashCode. И для создания копии - метод Copy. Текущий код Client
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
    /// <summary>Класс представляющий клиента</summary>
    public class Client
    {
        /// <summary>Неизменяемый уникальный идентификатор</summary>
        public string ID { get; private set; }
        /// <summary>Имя, фамилия и отчество</summary>
        public string Name { get; set; }
        /// <summary>Дата рождения</summary>
        public DateTime DateOfBirth { get; set; }
        /// <summary>Пол: мужской, женский</summary>
        public SexEnum Sex { get; set; }
        /// <summary>Место работы</summary>
        public string Job { get; set; }
        /// <summary>Доход (рублей в месяц)/summary>
        public string Salary { get; set; }
        /// <summary>Контактные телефоны</summary>
        public string Telephone { get; set; }
 
        /// <summary>Статический конструктор создания экземпляра из XML</summary>
        /// <param name="ClientXML">XElement с данными</param>
        /// <returns>Новый экземпляр если данные корректны, иначе - null</returns>
        public static Client CreateFromXML(XElement ClientXML)
        {
            if (ClientXML.Name != "Client") // Проверка имени корневого элемента
                return null;
            if // Проверка наличия всех необходимых данных
            (
                ClientXML.Attribute("ID") == null
                || ClientXML.Element("Name") == null
                || ClientXML.Element("DateOfBirth") == null
                || ClientXML.Element("Sex") == null
                || ClientXML.Element("Job") == null
                || ClientXML.Element("Salary") == null
                || ClientXML.Element("Telephone") == null
                || !DateTime.TryParse(ClientXML.Element("DateOfBirth").Value, out DateTime dateOfBirth)
                || !Enum.TryParse(ClientXML.Element("Sex").Value, true, out SexEnum sex)
             ) return null;
 
            return new Client()
            {
                ID = ClientXML.Attribute("ID").Value,
                Name = ClientXML.Element("Name").Value,
                DateOfBirth = dateOfBirth,
                Sex = sex,
                Job = ClientXML.Element("Job").Value,
                Salary = ClientXML.Element("Salary").Value,
                Telephone = ClientXML.Element("Telephone").Value
            };
        }
 
        /// <summary>Преобразует в XML</summary>
        /// <returns>XElement нужной структуры с нужными данными</returns>
        public XElement ToXML() => XElement.Parse
            (
                $"<Client ID=\"{ID?.Trim()}\">" +
                    $"<Name>{Name?.Trim()}</Name>" +
                    $"<DateOfBirth>{DateOfBirth.ToString()}</DateOfBirth>" +
                    $"<Sex>{Sex.ToString().Trim()}</Sex>" +
                    $"<Job>{Job?.Trim()}</Job>" +
                    $"<Salary>{Salary?.Trim()}</Salary>" +
                    $"<Telephone>{Telephone?.Trim()}</Telephone>" +
                $"</Client>"
             );
 
        /// <summary>Метод создания нового уникального ID</summary>
        /// <param name="Clients">Список существующих Client</param>
        /// <returns>Случайный ID которого нет в списке переданных Client</returns>
        public static string NewID(IEnumerable<Client> Clients)
        {
 
            Random rnd = new Random();
            string id;
            do
            {
                // Создаём в цикле новые ID до тех пор пока не найдём
                // несуществующий в переданном списке
                id = "Cl" + rnd.Next(1000000).ToString().PadLeft(6, '0');
            } while (Clients.FirstOrDefault(client => client.ID == id) != null);
            return id;
        }
 
        /// <summary>Возвращает список допустимых полов</summary>
        public SexEnum[] ListSex => (SexEnum[])Enum.GetValues(typeof(SexEnum));
 
        /// <summary>Перечисление допустимых полов</summary>
        public enum SexEnum
        {
            Мужской = 1,
            Женский = 2
        }
 
        /// <summary>Копирует объект</summary>
        /// <returns>Возвращает новый объект копию</returns>
        public Client Copy() => new Client()
        {
            ID = ID,
            Name = Name,
            DateOfBirth = DateOfBirth,
            Sex = Sex,
            Job = Job,
            Salary = Salary,
            Telephone = Telephone
        };
 
        public override bool Equals(object obj)
        {
            var client = obj as Client;
            return client != null &&
                   ID == client.ID &&
                   Name == client.Name &&
                   DateOfBirth == client.DateOfBirth &&
                   Sex == client.Sex &&
                   Job == client.Job &&
                   Salary == client.Salary &&
                   Telephone == client.Telephone;
        }
 
        public override int GetHashCode()
        {
            var hashCode = -1522303320;
            hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(ID);
            hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(Name);
            hashCode = hashCode * -1521134295 + DateOfBirth.GetHashCode();
            hashCode = hashCode * -1521134295 + Sex.GetHashCode();
            hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(Job);
            hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(Salary);
            hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(Telephone);
            return hashCode;
        }
    }
0
3 / 2 / 1
Регистрация: 10.10.2015
Сообщений: 24
29.11.2018, 20:25  [ТС]
Для чего указывать аттрибут [ValueConversion]? Что он дает? Какое его предназначение? Сколько не читал про атрибуты, так и не понимаю.
Можно ли обойтись без переопределения метода GetHashCode()?

Завтра буду разбираться...
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16152 / 11273 / 2890
Регистрация: 21.04.2018
Сообщений: 33,147
Записей в блоге: 2
29.11.2018, 21:32
Цитата Сообщение от RussianVodkaL Посмотреть сообщение
Для чего указывать аттрибут [ValueConversion]? Что он дает? Какое его предназначение? Сколько не читал про атрибуты, так и не понимаю.
Это дополнительные указания для платформы Net. Используется при рефлексии. ValueConversion - указывает что конвертер из одного типа в другой.
Цитата Сообщение от RussianVodkaL Посмотреть сообщение
Можно ли обойтись без переопределения метода GetHashCode()?
Можно, но при переопределении только метода Equals будет постоянно выдавать предупреждение. Среда Net в некоторых случаях использует метод Equals , в некоторых GetHashCode. Поэтому желательно чтобы они были согласованны. Тем более что в конструкторе класса (в быстрых решениях) они вставляются вместе, надо только указать какие свойства и поля для них надо использовать.
0
3 / 2 / 1
Регистрация: 10.10.2015
Сообщений: 24
30.11.2018, 11:02  [ТС]
В принципе все понятно.

Вопрос на счет конвертеров: правильно ли я понял, что мы можем конвертировать, например, тот же тип Visibility в, например, тип int или double? И задать установку своих значений, которые будут соответствовать значениям в классе Visibility?
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16152 / 11273 / 2890
Регистрация: 21.04.2018
Сообщений: 33,147
Записей в блоге: 2
30.11.2018, 11:42
Цитата Сообщение от RussianVodkaL Посмотреть сообщение
Вопрос на счет конвертеров: правильно ли я понял, что мы можем конвертировать, например, тот же тип Visibility в, например, тип int или double? И задать установку своих значений, которые будут соответствовать значениям в классе Visibility?
Как пример - да, можем. Но возможности намного шире. Допустим, надо изменить вид элемента, если его значение станет больше 5. Стандартными WPF возможностями это сделать невозможно. Надо сделать конвертер который сравнивает значение и возвращает bool результат и потом использовать этот конвертер в триггерах. В общем, в любых местах, где требуется преобразование данных в XAML.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16152 / 11273 / 2890
Регистрация: 21.04.2018
Сообщений: 33,147
Записей в блоге: 2
30.11.2018, 19:47
Столкнулся с неожиданной проблемой - метод Equals не должен давать равенство для разных объектов. Иначе XAML начинает гнать. Переделал Equals. А для сравнения объектов создал в клиенте метод Unequally.
Завершил VM времени исполнения. Может ещё какие мелкие доработки - не помню.
Весь проект в рабочем виде приложен.
Погоняйте его, посмотрите. Может ошибки где есть.
Какие вопросы появятся - задавайте.
Вложения
Тип файла: 7z DataLoadDataGrid(Wpf).7z (45.5 Кб, 27 просмотров)
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16152 / 11273 / 2890
Регистрация: 21.04.2018
Сообщений: 33,147
Записей в блоге: 2
30.11.2018, 20:04
Самое главное забыл-то написать. С чего вся тема начиналась.
Посмотрите в модели я добавил вызов события PropertyChanged в методах которые изменяют данные Add, RemoveID и ChangeID. При вызове события я передаю имя "Список", но такого свойства нет нигде в проекте.
В VM в методе Model_PropertyChanged я перехватываю это событие и проверяю переданное значение, если это "Список", то обновляю свойство Clients. Из этого ясно, что событие PropertyChanged это всего лишь передача какой-то стринговой переменной. Ни какого бОльшего функционала оно не несёт. Само по себе оно не может обновлять значения свойств.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
30.11.2018, 20:04
Помогаю со студенческими работами здесь

Загрузка данных из XML файла в ClientDataSet (xml как база данных)
Написал обработчик xml по примерам из инета, суть состоит в том чтобы считать по заданному тегу все его дочерние теги и значения в них...

Загрузка данных из MySql в DataGrid
Я считываю данные из таблицы таким образом Dim b As Integer = 0 Form1.Sqlcon.Open() Form1.cmd.CommandText =...

Загрузка данных из datagrid в datatable
Доброго времени суток, уважаемые знатоки. Собственное ТЗ: Есть база данных на firebird, мое (WPF) приложение успешно подключается к...

Сохранение данных из DataGrid в XML
Есть XML файл: &lt;?xml version=&quot;1.0&quot; standalone=&quot;yes&quot;?&gt; &lt;learners&gt; &lt;learner&gt; &lt;id&gt;1&lt;/id&gt; &lt;Name&gt;Marina&lt;/Name&gt; ...

Загрузка данных из таблицы Access в DataGrid
Мне нужно сделать приложение в Wpf, используя базу данных Access 2010. После добавления базы в источники данных, пробую загрузить вот так:...


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

Или воспользуйтесь поиском по форуму:
34
Ответ Создать тему
Новые блоги и статьи
Транскрипция 55-минутного видео через Whisper: WhisperDesktop облажался, спас Google Colab[
anaschu 01.06.2026
Понадобилось получить текст из свежезагруженного видео на YouTube. Казалось бы, задача на пять минут. Заняла полтора часа. Делюсь опытом — может кому пригодится последовательность решений. . . .
21 мат мед. Планы на развитие модели здравоСохранения
anaschu 01.06.2026
AnyLogic: план развития симуляционной модели рабочего коллектива — динамический абсентеизм, реальные данные, три сценария сравнения Продолжаю серию постов о дискретно-событийной модели рабочего. . .
20. Мат мед. Абсентеизм как отдельный тип простоя
anaschu 29.05.2026
Апдейт модели: исправленные баги, абсентеизм и новые механизмы Продолжаю развивать ранее описанную модель рабочего коллектива на AnyLogic. За последние несколько дней был проведён серьёзный. . .
19. здоровье, усталость и психотип работника влияют на производительность предприятия, и наоборот, производительность на здоровье, усталось и психотип
anaschu 28.05.2026
Дискретно-событийная модель рабочего коллектива на AnyLogic: здоровье, выгорание, психотипы и микростимуляция Привет, коллеги. Хочу поделиться итогами нескольких недель работы над симуляционной. . .
"Прокси" для последовательного порта
Eddy_Em 28.05.2026
Эту штуку написал я достаточно давно. Но сейчас вот понадобилось настроить датчик грозы, но при этом не отключать его от "метеодемона". Соответственно, надо запустить этот "прокси": метеодемон будет. . .
Рефакторинг программы уравнивания.
Massaraksh7 26.05.2026
Пример по предыдущей записи в блоге. Но, надо заметить, что, во-первых, там оптимизация не только математики, но и работы с базой данных, и с графами, а во-вторых, это ещё не всё.
Использование TThread в Lazarus для математических вычислений.
Massaraksh7 25.05.2026
Производя рефакторинг своих программ на предмет ускорения их работы, обратил внимание на такой аспект, как сокращение времени матвычислений. Дело в том, что приходится работать с большими матрицами. . .
Модель здравосохранения 18. Чем здоровее работник, тем быстрее выгорает
anaschu 24.05.2026
Имитационная модель корпоративного здравоохранения: что показывает математика Сегодня в модели рабочего коллектива на AnyLogic появились три новые механики — выгорание через накопленную усталость,. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru