Здравствуйте. Столкнулся с проблемой. Делаю приложение на WPF с использованием паттерна MVVM. Работу с базой данных осуществляю с помощью Entity Framework. Есть 2 таблицы: Сотрудники(ФИО, id должности) и Должности(id, название). Я хочу, чтобы на форме с сотрудниками, когда я выбираю одного из них, выводилась вся информация о нём (ФИО, должность и тд). Это я осуществил, создав класс EmployeesViewModel:
class EmployeesViewModel : INotifyPropertyChanged
{
OpticsEntities db;
private Employee selectedEmployees;
public ObservableCollection
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 должности.
Ответ
Тут достаточно много вариантов реализации, красивых и не очень, но если попробовать сделать с участием дополнительной коллекции моделей представления для каждой должности, как вы описали.
Пример искусственный, написан для демонстрации подхода к использованию тонкостей привязки 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, IEnumerable
public Employee Model { get; set; }
public IEnumerable
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
Надеюсь, принцип понятен и удастся перенести это на ваш случай.
Комментариев нет:
Отправить комментарий