With Caliburn.Micro I'd like to know the pros and cons of exposing an EF4 Entity as a property of the ViewModel (a technique discussed here and here). This allows me to avoid writing getters and setters for every field (see OneCustomer below). The drawback is I need to write all of the binding statements in XAML (below LastName is not in the ViewModel but does require XAML binding). If I stick to the prescribed technique of filling my ViewModel with properties for each field (as FirstName below) I'll ultimately have to write a ton of extra code just so NotifyOfProperyChange will get called. The application will be quite large. Should I expose each entity as a property of the ViewModel?
In My ViewModel:
private MyEntities _context = new MyEntities();
private BindableCollection<Customer> _custBindableCollection;
private Customer _oneCustomer;
private string _firstName;
public void Load()
{
_custBindableCollection = new BindableCollection<Customer>(_context.Customers.Where(row => row.CustomerType == "FOO"));
AllCustomers = _custBindableCollection;
_oneCustomer = _custBindableCollection.FirstOrDefault();
FirstName = _oneCustomer.FirstName;
OneCustomer = _oneCustomer;
}
public BindableCollection<Customer> AllCustomers
{
get { return _custBindableCollection;}
set {_custBindableCollection = value;
NotifyOfPropertyChange(() => AllCustomers);}
}
public Customer OneCustomer
{
get { return _oneCustomer;}
set { _oneCustomer = value;
NotifyOfPropertyChange(() => OneCustomer);}
}
public string FirstName
{
get { return _firstName; }
set {
_firstName = value;
_oneCustomer.FirstName = value;
NotifyOfPropertyChange(() => FirstName);
NotifyOfPropertyChange(() => CanSaveChanges);
}
}
public void SaveChanges()
{ _context.SaveChanges(); }
public bool CanSaveChanges { get { return IsValid; } }
In My View:
<StackPanel>
<StackPanel Orientation="Horizontal">
<Label Content="First Name:" />
<TextBox x:Name="FirstName" />
</StackPanel>
<StackPanel Orientation="Horizontal" DataContext="{Binding Path=OneCustomer}">
<Label Content="Last Name:" />
<TextBox x:Name="LastName" Text="{Binding LastName}" />
</StackPanel>
<Button Content="Load Data" x:Name="Load" />
<Button Content="Save" x:Name="SaveChanges" />
<DataGrid x:Name="AllCustomers" />
Thanks in advance.
With Caliburn.Micro I'd like to know the pros and cons of exposing an EF4 Entity as a property of the ViewModel (a technique discussed here and here).
I'm not sure of the pros/cons but I can tell you both methods are used. For example take a simple Login Screen, generally I put the UserName a property on the ViewModel but in cases where the form is more complex the ViewModel can aggregate other ViewModels(display models) to accomplish the same thing. CM doesn't effect the pros/cons much as its more a question of With MVVM, what are the pros/cons. CM is going to help you in binding to both.
So from your xaml above:
<TextBox x:Name="LastName" Text="{Binding LastName}" />
you don't need to set the DataContext on the StackPanel. Instead:
<TextBox x:Name="OneCustomer_LastName"/>
One thing that can make binding to DataForms and DataGrids easier is following a method where you create display models for the way the data is represented on the screen.
This is my opinion but I personally will never bind directly to an EF/Linq entity. Instead I'll create a display model to represent that entity and how I want it displayed and use AutoMapper to do the mappings. In a lot of cases its a one to one mapping. This might seem like a waste of time but it has advantages especially with more complex data model layouts, display models allow you to flatten the data for display purposes and attribute up properties for validation without sticking them on the data model entity. For more on that check out the chapter on it in ASP.NET MVC in Action book.
Since there are other advantages of exposing entities (for example, validation through attributes), I personally do expose them directly.
But I guess the proper answer would be "it depends" as there are always some drawbacks too (mainly architectural).
BTW: you can call the textbox "OneCustomer_LastName" and C.M's convention binding will work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With