Reputation: 177
Trynig to set DataContext to WPF Window I am using CodeFirst and here is the code
public class Employee
{
[Key]
public int EmployeeId { get; set; }
[Display(Name = "FullName")]
[Required(ErrorMessage = "FullNameRequired")]
public string FullName { get; set; }
public string Address { get; set; }
public string Phone { get; set; }
public double Salary { get; set; }
public string Email { get; set; }
public string Job { get; set; }
}
public class EmployeeVM
{
SDBContext db = new SDBContext();
public List<Employee> Employees;
public EmployeeVM()
{
this.Employees= db.Employees.ToList();
}
}
added the ViewModel to the window datacontext
xmlns:VM="clr-namespace:Project_Test.ViewModels"
<Window.DataContext>
<VM:EmployeeVM/>
</Window.DataContext>
But I get the error "invalid column name Job"
and I tried binding 'Employees' Collection to DataGrid but it didn't work
ItemsSource="{Binding Employees}"
Done that in codebehind and it works fine
SDBContext db = new SDBContext();
public MainWindow()
{
InitializeComponent();
DG_Employees.ItemsSource = db.Employees.ToList();
}
Update
I deleted the attribute 'Job' and got another error: "the model backing the context has changed since the database was created. consider using code first"
Upvotes: 0
Views: 367
Reputation: 531
For your first approach to work, your Employees
has to be property, not field, like this:
public class EmployeeVM
{
SDBContext db = new SDBContext();
public List<Employee> Employees {get;set;}
public EmployeeVM()
{
this.Employees= db.Employees.ToList();
}
}
Then when you bind ItemsSource to your Employees it should work.
But.
If you plan loading Employees from database somewhere except costructor, your EmployeeVM
should implement INotifyPropertyChanged and Employees
property should raise PropertyChanged
event on change, so your Viewmodel should look like:
public class EmployeeVM : INotifyPropertyChanged
{
SDBContext db = new SDBContext();
private List<Employee> _employees;
public List<Employee> Employees
{
get { return _employees; }
set
{
if (Equals(value, _employees)) return;
_employees = value;
OnPropertyChanged("Employees");
}
}
public EmployeeVM()
{
this.Employees = db.Employees.ToList();
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
Then, every time you do this.Employees = /..something../
your bound DataGrid should see ItemsSource changed.
But even more, if you plan to let user add/remove Employees
from DataGrid or in some other way modify Employees
collection , you should change Employees
property type from List<Employee>
to ObservableCollection<Employee>
, and then your View (e.g. DataGrid) should get events whenever new Employee will be removed or added to Employees
collection.
And there's more, if you plan changing Employee's properties like FullName
etc and want these changes to be noticed by view (e.g. DataGrid to update corresponding cell after Eployee's FullName
was changed) your Employee class, in turn, should implement INotifyPropertyChanged too - but even better, you let alone Employee which is a part of Model and loaded from database and create separate viewmodel for Employee class.
I have to add, if your task is only to load Employees from database once on ViewModel construction, get them to View, read-only, no editions, updates or deletions, you could omit all the hassle above, but I think that's a rare scenario.
Upvotes: 0