При загрузке данных из БД возникает исключение InvalidOperationException с сообщением: Элемент коллекции должен быть пустым перед использованием ItemsSource. Знаю, что для заполнения DataGrid можно использовать коллекции Items или ItemsSource, но одновременно их использовать нельзя: если задано значение для свойства ItemsSource и в коде C# добавляется элемент в Items, возникает исключение. |
Взаимодействие приложения с базой данных
Редактирование, вставка и удаление данных
Для редактирования данных в приложении модифицируем метод EditCommandBinding_Executed
private void EditCommandBinding_Executed(object sender, ExecutedRoutedEventArgs e) { DataGridEmployee.IsReadOnly = false; DataGridEmployee.BeginEdit(); isDirty = false; }
Свойству IsReadOnly сетки DataGridEmployee присвоим значение false, что обеспечит возможность редактирования строк и ячеек сетки. Далее используем метод BeginEdit для начала редактирования ячейки, на которую наведен указатель мыши.
Результаты редактирования необходимо сохранить в базе данных. Для этого необходимо вызвать метод SaveCommandBinding_Executed.
private void SaveCommandBinding_Executed(object sender, ExecutedRoutedEventArgs e) { DataEntitiesEmployee.SaveChanges(); isDirty = true; DataGridEmployee.IsReadOnly = true; }
В методе SaveCommandBinding_Executed вызывается метод SaveChanges класса dataEntitiesEmployee. Метод SaveChanges сохраняет все обновления в источнике данных.
Для создания данных по новому сотруднику модифицируем метод NewCommandBinding_Executed.
private void NewCommandBinding_Executed(object sender, ExecutedRoutedEventArgs e) { Employee employee = Employee.CreateEmployee(-1, "не задано", "не задано", "не задано", 0); employee.Telephone = "не задано"; employee.Email = "не задано"; try { DataEntitiesEmployee.Employees.AddObject(employee); ListEmployee.Add(employee); DataGridEmployee.ScrollIntoView(employee); DataGridEmployee.SelectedIndex = DataGridEmployee.Items.Count - 1; DataGridEmployee.Focus(); DataGridEmployee.IsReadOnly = false; isDirty = false; } catch (DataServiceRequestException ex) { throw new ApplicationException( "Ошибка добавления нового сотрудника в контекст данных" + ex.ToString()); } }
В методе NewCommandBinding_Executed объект employee класса Employee создается с помощью метода CreateEmployee, параметрами которого являются ID, которое задается равным -1, Surname, Name и Patronymic, которым задается значение "не задано" и TitleID со значением 0. Кроме того, свойствам Telephone и Email объекта employee присваивается строковое значение "не задано". В блоке try ... catch созданный объект employee добавляется в контекст данных методом AddObject сущности Employees EDM-модели DataEntitiesEmployee, а также в коллекцию ListEmployee. Затем производится прокрутка сетки, выделение и перемещение фокуса на созданный объект.
DataGridEmployee.ScrollIntoView(employee); DataGridEmployee.SelectedIndex = DataGridEmployee.Items.Count - 1; DataGridEmployee.Focus();
При инициализации команды создания данных по новому сотруднику в сетке формируется первоначальная строка с данными "по умолчанию" ( рис. 5.12). В сформированную строку необходимо ввести реальные данные сохранить их, вызвав команду "Сохранить".
Для удаления данных по сотруднику используем метод DeleteCommandBinding_Executed.
private void DeleteCommandBinding_Executed(object sender, ExecutedRoutedEventArgs e) { Employee emp = DataGridEmployee.SelectedItem as Employee; if (emp != null) { MessageBoxResult result = MessageBox.Show("Удалить сотрудника: " + emp.Surname + " " +emp.Name + " " + emp.Patronymic, "Предупреждение", MessageBoxButton.OKCancel); if (result == MessageBoxResult.OK) { DataEntitiesEmployee.DeleteObject(emp); DataGridEmployee.SelectedIndex = DataGridEmployee.SelectedIndex == 0 ? 1 : DataGridEmployee.SelectedIndex - 1; ListEmployee.Remove(emp); DataEntitiesEmployee.SaveChanges(); } } else { MessageBox.Show("Выберите строку для удаления"); } }
В методе определяем объект emp класса Employee, который выделен в сетке DataGridEmployee.
Employee emp = DataGridEmployee.SelectedItem as Employee;
Если объект emp найден, то с помощью диалогового окна класса MessageBoxResult выводим сообщение с данными о сотруднике, которого предполагается удалить.
MessageBoxResult result = MessageBox.Show("Удалить сотрудника: " + emp.Surname + " " + emp.Name + " " + emp.Patronymic, "Предупреждение", MessageBoxButton.OKCancel);
При подтверждении операции удаления объект emp удаляется из контекста методом DeleteObject.
DataEntitiesEmployee.DeleteObject(emp);
Далее формируется в сетке DataGridEmployee выделяемая строка.
DataGridEmployee.SelectedIndex = DataGridEmployee.SelectedIndex == 0 ? 1 : DataGridEmployee.SelectedIndex - 1;
Объект emp удаляется из коллекции ListEmployee.
ListEmployee.Remove(emp);
Изменения вносятся в базу данных.
DataEntitiesEmployee.SaveChanges();
Страница PageEmployee при выполнении операции удаления данных по сотруднику приведена на рис. 5.13.
Метод UndoCommandBinding_Executed реализует отмену редактирования последних элементов сетки DataGridEmployee и переводит её в режим просмотра.
Для реализации данной функциональности необходимо провести некоторые изменения в коде приложения. Для метода Page_Loaded основной код выделим в метод GetEmployees.
private void GetEmployees() { ObjectQuery<Employee> employees = DataEntitiesEmployee.Employees; var queryEmployee = from employee in employees orderby employee.Surname select employee; foreach (Employee emp in queryEmployee) { ListEmployee.Add(emp); } DataGridEmployee.ItemsSource = ListEmployee; }
С учетом созданного метода GetEmployees метод Page_Loaded будет иметь следующий вид.
private void Page_Loaded(object sender, RoutedEventArgs e) { GetEmployees(); DataGridEmployee.SelectedIndex = 0; }
Создадим метод RewriteEmployee, который будет обновлять контекст данных и коллекцию ListEmployee.
private void RewriteEmployee() { DataEntitiesEmployee = new TitlePresonalEntities(); ListEmployee.Clear(); GetEmployees(); }
С учетом проведенных модификаций кода метод UndoCommandBinding_Executed будет иметь следующий вид.
private void UndoCommandBinding_Executed(object sender, ExecutedRoutedEventArgs e) { RewriteEmployee(); DataGridEmployee.IsReadOnly = true; isDirty = true; }
При запуске команды Отмена будет отменено редактирование в текущей ячейке сетки, а если редактировались несколько ячеек, то при повторном запуске команды будет обновлена вся строка.