简体   繁体   中英

WPF MVVM master-detail collections with Entity Framework

I have 2 comboboxes in WPF, both binded to ObservableCollections under ViewModel:

<ComboBox ItemsSource="{Binding Companies}" SelectedItem="{Binding Path=SelectedCompany,Mode=TwoWay}" />
<ComboBox ItemsSource="{Binding Employees}" SelectedItem="{Binding Path=SelectedEmployee,Mode=TwoWay}" />

In ViewModel I have:

Public Property Companies As ObservableCollection(Of Company)
Public Property Employees As ObservableCollection(Of Employee)
Public Property SelectedCompany As Company
Public Property SelectedEmployee As Employee

On initializing the ViewModel, I ask all the Companies from the repository (that itself uses Linq-to-Entities query), which returns the Companies as IEnumerable (Of Company):

Public Sub New()    
    Companies = New ObservableCollection(Of Company)(_CompanyRepo.GetAll())
End Sub

Up to this point everything works ok. But now I need to get data to the Employees collection (there is a repository for it returning IEnumerable as well) and want only the Employees data for the selected Company at any time.

How do I do it in the ViewModel? Employees Combobox should update itself any time SelectedItem is changed in Company Combobox.

Company and Employee have a one-to-many relation within the Entity Framework. Can I utilize that fact somehow? Can I avoid repeating Linq-to-Entity queries somehow by caching data?

You can bind to the navigation property of entity framework. Use an observable collection for the Company combobox and bind the employee combobox to the navigation property.

So in ViewModel you only need:

Public Property Companies As ObservableCollection(Of Company)
Public Property SelectedCompany As Company
Public Property SelectedEmployee As Employee

Lets say that your entity framework has a navigation property on your comapny entity named company_employee. You can bind directly to that in your view like:

<ComboBox ItemsSource="{Binding SelectedCompany.company_employee}" SelectedItem="{Binding Path=SelectedEmployee,Mode=TwoWay}" />

WPF and entity framework will get the required data for you. and it will only be the employees that have the matching company.

WHat I do is use a usercontrol as my view and have a grid/usercontrol/contentcontrol that would bind (set its datacontext) to the SelectedCompany in side my View.

ie

<ContentControl Name="DetailControl" DataContext="{Binding Path=SelectedCompany, Mode=TwoWay}" >

Then within that contentcontrol the binding for a combox or datagrid or listview is as follows if you still want to have a selectedemployee binding:

<ComboBox ItemsSource="{Binding company_employee}" SelectedValue="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}},Path=DataContext.SelectedEmployee}" />

But if you don't need the selectedEMployee you can just bind to the EMployeeID in the company Table as follows:

<ComboBox ItemsSource="{Binding company_employee}" SelectedValue="{Binding EmplyeeID, Mode=TwoWay" />

You just bind directely to the navigation property and use the employee Foreign key.

I just typed these out so you might need to double check all the names etc.. Hope these options help

EDIT 1:

Include example (in vb.net)

 Dim MyQuery As IQueryable(Of Company) = CType((From MyResults In Context.Company.Include("Employee") Select MyResults), IQueryable(Of Company))

see: Include Method MSDN Documentation

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM