#wpf #mvvm #combobox
Здравствуйте. Столкнулся с проблемой. Делаю приложение на WPF с использованием паттерна MVVM. Работу с базой данных осуществляю с помощью Entity Framework. Есть 2 таблицы: Сотрудники(ФИО, id должности) и Должности(id, название). Я хочу, чтобы на форме с сотрудниками, когда я выбираю одного из них, выводилась вся информация о нём (ФИО, должность и тд). Это я осуществил, создав класс EmployeesViewModel: class EmployeesViewModel : INotifyPropertyChanged { OpticsEntities db; private Employee selectedEmployees; public ObservableCollectionEmployees { get; set; } public Employee SelectedEmployees { get { return selectedEmployees; } set { selectedEmployees = value; OnPropertyChanged("SelectedEmployees"); } } public EmployeesViewModel() { db = new OpticsEntities(); db.Employees.Load(); Employees = db.Employees.Local; } public event PropertyChangedEventHandler PropertyChanged; public void OnPropertyChanged([CallerMemberName]string prop = "") { if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(prop)); } private RelayCommand addCommand; private RelayCommand saveCommand; private RelayCommand removeCommand; private RelayCommand changeCommand; public RelayCommand AddCommand { get { return addCommand ?? (addCommand = new RelayCommand(obj => { Employee employees = new Employee(); Employees.Insert(0, employees); SelectedEmployees = employees; })); } } public RelayCommand SaveCommand { get { return saveCommand ?? (saveCommand = new RelayCommand(obj => { Employee employees = obj as Employee; if (employees != null) { db.Employees.Add(employees); db.SaveChanges(); } })); } } public RelayCommand ChangeCommand { get { return changeCommand ?? (changeCommand = new RelayCommand(obj => { Employee employees = obj as Employee; if (employees != null) { var changeEmployees = db.Employees.Find(employees.id); employees = changeEmployees; db.SaveChanges(); } })); } } } и представление: Всё отлично работает. Можно добавить нового сотрудника и сохранить. Но проблема вот в чем. Поле "Должность" связано с таблицей "Должности" по внешнему ключу (id). И я хочу, чтобы вместо текстового поля с id должности был ComboBox, в котором бы находились названия всех должностей из таблицы "Должности". По умолчанию в нем была бы та должность, которой соответствует сотрудник, но можно было бы открыть ComboBox и присвоить ему другую. После нажатия на Save всё сохранилось бы в базе. Максимум, что я смог сделать, это создать ComboBox, в котором будут отображаться эти должности. Но для этого пришлось сделать еще одну коллекцию во ViewModel и обращаться уже к ней в ItemsSource. Естественно, что бы я в ней не выбрал, никакой связи с сотрудником не будет, так как данные не связаны получается. Как мне сделать, чтобы в ComboBox отображались должности из таблицы Должности, и при выборе одной из них она бы присваивалась полю Должность у Сотрудника? Напомню, что таблицы связаны внешним ключом по id должности.
Ответы
Ответ 1
Тут достаточно много вариантов реализации, красивых и не очень, но если попробовать сделать с участием дополнительной коллекции моделей представления для каждой должности, как вы описали. Пример искусственный, написан для демонстрации подхода к использованию тонкостей привязки ComboBox к данным, ни в коем случае не является примером реализации правильного MVVM. Модели сущностей предметной области: public class Employee { public string Name { get; set; } public int PostID { get; set; } } public class Post { public int ID { get; set; } public string Name { get; set; } } Модели представления: public class EmployeeViewModel : NotificationObject { public EmployeeViewModel(Employee model, IEnumerableposts) { Model = model; var postViewModels = new List (); foreach (var post in posts) { postViewModels.Add(new PostViewModel(post)); } PostViewModels = postViewModels; } public Employee Model { get; set; } public IEnumerable PostViewModels { get; private set; } } public class PostViewModel : NotificationObject { public PostViewModel(Post model) { Model = model; } public Post Model { get; set; } } Класс NotificationObject просто реализует INotifyPropertyChanged. В DataContext окна попадает EmployeeViewModel. Разметка: Пример работающий, в Combobox будут отображаться названия должностей, при этом в объект Employee при выборе в ComboBox будет присваиваться валидный идентификатор должности. У ComboBox есть несколько крайне полезных свойств. DisplayMemberPath - путь к свойству сущности в DataContext элемента списка ComboBox, который будет отображаться в выпадающем списке и в основном теле ComboBox. SelectedValue - наравне с SelectedItem можно биндиться к свойству SelectedValue, значение которого берётся по определённому пути из SelectedItem. SelectedValuePath - путь от SelectedItem, по которому берётся SelectedValue. В моём примере при выборе в ComboBox в его свойство SelectedItem попадает PostViewModel, а в свойство SelectedValue попадает уже искомый идентификатор должности. Это свойство и забиндено на PostID сущности Employee. Надеюсь, принцип понятен и удастся перенести это на ваш случай.
Комментариев нет:
Отправить комментарий