I thought I would give the Xceed WPF DataGrid (it’s free!) a whirl with Entity Framework databinding. So far I have only explored the basics – no anonymous types or sprocs and I am only working with a READ-ONLY scenario. (I did notice something in their docs about being able to modify and delete but not add when binding to LINQ to SQL queries.) I have, however, at least used a multi-level object graph.
Here’s what I’ve come up with.
Add the grid
- Drop an Xceed WPF DataGrid on a WPF Window
Preparing the data
- I created an EDM from AdventureWOrksLT. The namespace is awModel and the EntityContainer is awEntities. I also fixed up some naming, plurazing the EntitySets and the navigation properties that point to collections. (This is my standard routine when creating EDMs)
- In the Loaded event for the WIndow, add the following
Dim aw = New awModel.awEntitiesMe.DataGridControl1.ItemsSource = From ord In aw.SalesOrderHeaders.Include(“Customer”) _
Select ord
Setting up the grid for Databinding
If you’ve never used WPF, or done databinding in WPF, there are definitely a lot of new things to learn! The easiest thing to do for now is just copy and paste all of this XAML below.
Here’s what the entire XAML looks like.
<Window x:Class=”Window2″
xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”
xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”
Title=”Window2″ Height=”300″ Width=”300″ Name=”Window1″ xmlns:xcdg=”http://schemas.xceed.com/wpf/xaml/datagrid”
xmlns:local=”clr-namespace:WpfApplication1.awModel”>
<Grid>
<Grid.Resources>
<DataTemplate DataType=”{x:Type local:SalesOrderHeader}”>
<TextBlock Text=”{Binding TotalDue}”/>
</DataTemplate>
<DataTemplate DataType=”{x:Type local:Customer}”>
<TextBlock Text=”{Binding Customer.CompanyName}”/>
</DataTemplate>
</Grid.Resources>
<xcdg:DataGridControl Margin=”10,9,4,0″ Name=”DataGridControl1″ ItemsSource=”{Binding}” >
<xcdg:DataGridControl.Columns>
<xcdg:Column FieldName=”Customer.CompanyName” Title=”Company” />
<xcdg:Column FieldName=”TotalDue” Title=”Total Due”/>
</xcdg:DataGridControl.Columns>
</xcdg:DataGridControl>
</Grid>
</Window>
The xml namespace tag xdcg get’s added automatically when you drop the DataGrid on the window.
The xml namespace tag “local” is something I added. It’s necessary for subsequent references to classes from my EDM. Intellisense will help you pick the right namespace (your app and your model name) if you start with clr-namespace:.
In my query, I queried for SalesOrderHeaders plus their customer EntityRefs. In the DataTemplates, you can see that I’m referencing the actual object model types and then binding to the property from the SalesOrderHeader that is returned in my query. “TotalDue” gets me “SalesOrderHeader.TotalDue” and “Customer.CompanyName” gets me “SalesOrderHeader.Customer.CompanyName”. The DataTemplate provides binding to the data source (defined in the ItemsSource setting in the code above). Then the DataGrid column tie back to the bindings by way of the FieldName property.
Run the app
Note that I did not sort in my query. I wanted to demonstrate the grid’s built in sorting , but for some reason it’s not working in this scenario (stay tuned…I’ll get to the bottom of that).
The automatic grouping does work, though. AdventureWorksLT is not great for seeing this. Only Thrifty Parts and Sales happens to have more than one order.
Sign up for my newsletter so you don't miss my conference & Pluralsight course announcements!
Julie,Thanks for the nice article. I just wanted to find out if you had made any progress with the sorting issue?I have a two-way bound grid that is working very well. (Including combo-box’s for the columns which link to other entities via FKs in the database). However, the xceed grid sorting (and grouping in my case) is not happy.The element itself can be accessed via the FieldName attribute. So, for example, in a table of ‘Agents’, the FieldName ‘AgentTypeID’ gives the ID, via FK, of the AgentType in the appropriate table. I can then set the FieldName to ‘AgentType.AgentTypeName’ to show the actual agent type name. You have to love LINQ for this kind of OO – DB transparency.However, the xceed sorting (which I must admit I haven’t managed to examine yet), does not like the supplied field name.Judging by your article, you are on the same path, so please let me know if you find a suitable solution!Many thanks,Nicholas.
NicholasI put a question on the Xceed forums and will see what they come up with. forums.xceed.com/…/ShowPost.aspx are you binding to?Julie
Julie,Sounds great. I will keep exploring in the mean time.I am binding to a SQL DB. I used SQLMetal to generate the applicable DataContext child class.Thank you for your help. I will post if I find anything, and keep my eye on that xceed forum.Nicholas.
Julie,Bingo! It was the binding that had me fooled. The FieldName should be bound to the sortable attribute. (In my case the AgentTypeID). I then use a DisplayMemberBinding to control what the column displays:DisplayMemberBinding="{Binding Path=AgentType.AgentTypeName}"The only remaining issue is that, when I group by that column and get the group headers, they display the ID, and not the name. I will keep checking and hopefully blog some code later.Thanks again!Nick.(p.s. Sorry if I managed to double post!)
Julie, I have posted a reply concerning your issues with sorting. It is still availlable at the same address:http://forums.xceed.com/Forums/ShowPost.aspx?PostID=11292 I hope this will help you with your issues.Marcus
Interestingly I was doing a pretty common thing and it wasn’t working for sorting…I was binding a collection to a ComboBox, then binding the Grid to {Binding ElementName=theCombo, Path=SelectedValue} which was binding to the object selected.I then had the Grid’s ItemsSource bound to {Binding Path=MyRelatedCollection} (pre-fetched with a Span).This worked but didn’t support sorting…and none of this helped.What was wrong?EntityCollection doesn’t support reordering…So to fix it, handled hte ComboBox.SelectionChanged:Then wrapped the EntityCollection in an ObservableCollection (I am not positive this isn’t inefficent yet):EventEntity currentEvent = theDropDown.SelectedValue as currentEvent;grid.ItemsSource = new ObservableCollection<EventEntity>(currentEvent.Attendee.ToList<EventEntity>());Home this helps someone…it was a frustrating evening for me…
Yeah – EF not supporting sorting has bitten me in a number of places. I don’t thiknk I realized at the time I wrote this blog post that it was EF’s limitation.
Hi ThereI am trying to bind the EF to the xceed datagrid and I am struggling with where to start.Could you point in the right direction of some good exampls, documentation or any other resources you may have.Thanks
Julie,I added just a button to your app and called aw.SaveChanges() .I changed a value in the field TotalDue in the running app. Then I got the error "New transaction is not allowed because there are other threads running in the session."For me it seems that XCeed ist not working properly with EF???The only comment about SaveChanges & XCeed I found in xceed.com/…/18619.aspxwhere antonio is still waiting for an answer to that question as well…Regards,Peter
@Dean Although this blog post is over a year old, it seems to be where to start…a step by step walkthrough. I’m not sure what you are looking for in a starting point.@Peter,Yeah that sure sounds like an xceed problem. EF is not thread safe. I haven’t played with the grid since this blog post (note that its over a year old). Unfortunately, xceed is going to have to address this. I don’t know how I can help. I’d try escalating the question beyond the forums if a similar question has gone unanswered.
@peter – p.s., I was looking at my original post above and saw: "(I did notice something in their docs about being able to modify and delete but not add when binding to LINQ to SQL queries.)"I would hope that after a year, they’ve fixed that, but I wonder if its related?
Julie,thanks for your quick response. I am anxious for the answers from XCeed to my questions about that. At the moment I tried to make the Linq to Entity query to an observable collection: No Error, but – unfortunately – no change in the database and what is crazy for me: After aw.SaveChanges(); the value in field TotalDue switches back to the previous value… Well ahm…I’ll keep you informed, when I know something new.Peter
You know… in the latest versions we’ve added more support for EF. Are there still issues?
yes there are still the old same sorting issues. For me EF 4.0 is not ready to use in business, or you ever printed/scrolled and unsorted list?