Databinding With WPF - EF6 - Microsoft Learn
Databinding With WPF - EF6 - Microsoft Learn
In this walkthrough you can chose to implement a model using Code First or the EF
Designer. Complete one of the two following sections.
When using Code First development you usually begin by writing .NET Framework
classes that define your conceptual (domain) model.
C#
namespace WPFwithEFSample
{
public class Product
{
public int ProductId { get; set; }
public string Name { get; set; }
C#
using System.Collections.ObjectModel;
namespace WPFwithEFSample
{
public class Category
{
public Category()
public Category()
{
this.Products = new ObservableCollection<Product>();
}
The Products property on the Category class and Category property on the Product
class are navigation properties. In Entity Framework, navigation properties provide a
way to navigate a relationship between two entity types.
In addition to defining entities, you need to define a class that derives from DbContext
and exposes DbSet<TEntity> properties. The DbSet<TEntity> properties let the context
know which types you want to include in the model.
An instance of the DbContext derived type manages the entity objects during run time,
which includes populating objects with data from a database, change tracking, and
persisting data to the database.
Add a new ProductContext class to the project with the following definition:
C#
using System.Data.Entity;
namespace WPFwithEFSample
{
public class ProductContext : DbContext
{
public DbSet<Category> Categories { get; set; }
public DbSet<Product> Products { get; set; }
}
}
The database server that is installed with Visual Studio is different depending on the
version of Visual Studio you have installed:
If you are using Visual Studio 2010 you'll be creating a SQL Express database.
If you are using Visual Studio 2012 then you'll be creating a LocalDB database.
If you haven’t connected to a database from Server Explorer before you’ll need to
select Microsoft SQL Server as the data source
Connect to either LocalDB or SQL Express, depending on which one you have
installed, and enter Products as the database name
Select OK and you will be asked if you want to create a new database, select Yes
The new database will now appear in Server Explorer, right-click on it and select
The new database will now appear in Server Explorer, right click on it and select
New Query
Copy the following SQL into the new query, then right-click on the query and
select Execute
SQL
Select Data from the left menu and then ADO.NET Entity Data Model
If you are working in Visual Studio 2010 then you will need to update the EF designer to
use EF6 code generation.
Right-click on an empty spot of your model in the EF Designer and select Add
Code Generation Item…
Select Online Templates from the left menu and search for DbContext
Select the EF 6.x DbContext Generator for C#, enter ProductsModel as the name
and click Add
purpose use. This means that the entities generated from these templates have simple
ICollection<T> properties. However, when doing data binding using WPF it is desirable
to use ObservableCollection for collection properties so that WPF can keep track of
changes made to the collections. To this end we will to modify the templates to use
ObservableCollection.
Find the ProductModel.tt file which will be nested under the ProductModel.edmx
file
Save the ProductModel.tt file. This should cause the code for entities to be
regenerated. If the code does not regenerate automatically, then right click on
ProductModel.tt and choose “Run Custom Tool”.
If you now open the Category.cs file (which is nested under ProductModel.tt) then you
should see that the Products collection has the type ObservableCollection<Product>.
Lazy Loading
The Products property on the Category class and Category property on the Product
class are navigation properties. In Entity Framework, navigation properties provide a
way to navigate a relationship between two entity types.
EF gives you an option of loading related entities from the database automatically the
first time you access the navigation property. With this type of loading (called lazy
loading), be aware that the first time you access each navigation property a separate
query will be executed against the database if the contents are not already in the
context.
When using POCO entity types, EF achieves lazy loading by creating instances of
derived proxy types during runtime and then overriding virtual properties in your
classes to add the loading hook. To get lazy loading of related objects, you must declare
navigation property getters as public and virtual (Overridable in Visual Basic), and your
class must not be sealed (NotOverridable in Visual Basic). When using Database First
navigation properties are automatically made virtual to enable lazy loading. In the Code
First section we chose to make the navigation properties virtual for the same reason.
From the main menu, select Project -> Add New Data Source … (in Visual Studio
2010, you need to select Data -> Add New Data Source…)
In the Choose a Data Source Typewindow, select Object and click Next
In the Select the Data Objects dialog, unfold the WPFwithEFSample two times and
select Category
There is no need to select the Product data source, because we will get to it through
the Product’s property on the Category data source
the Product s property on the Category data source
Click Finish.
The Data Sources window is opened next to the MainWindow.xaml window If the
Data Sources window is not showing up, select View -> Other Windows-> Data
Sources
Press the pin icon, so the Data Sources window does not auto hide. You may need
to hit the refresh button if the window was already visible.
XML
<Window.Resources>
<CollectionViewSource x:Key="categoryViewSource"
d:DesignSource="{d:DesignInstance {x:Type
local:Category}, CreateList=True}"/>
</Window.Resources>
<Grid DataContext="{StaticResource categoryViewSource}">
<DataGrid x:Name="categoryDataGrid" AutoGenerateColumns="False"
EnableRowVirtualization="True"
ItemsSource="{Binding}" Margin="13,13,43,191"
RowDetailsVisibilityMode="VisibleWhenSelected">
<DataGrid.Columns>
<DataGridTextColumn x:Name="categoryIdColumn" Binding="
{Binding CategoryId}"
Header="Category Id"
Width="SizeToHeader"/>
<DataGridTextColumn x:Name="nameColumn" Binding="{Binding
Name}"
Header="Name" Width="SizeToHeader"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
Select the Products property from under the Category data source and drag it on
the form.
The categoryProductsViewSource resource and productDataGrid grid are
added to XAML
The binding path for this resource is set to Products
WPF data-binding framework ensures that only Products related to the selected
Category show up in productDataGrid
From the Toolbox, drag Button on to the form. Set the Name property to
buttonSave and the Content property to Save.
The form should look similar to this:
In the XAML window, click on the <Window element, this selects the main window
In the Properties window choose Events at the top right, then double-click the
text box to right of the Loaded label
Also add the Click event for the Save button by double-clicking the Save button in
the designer.
This brings you to the code behind for the form, we'll now edit the code to use the
g y
ProductContext to perform data access. Update the code for the MainWindow as shown
below.
C#
using System.Data.Entity;
using System.Linq;
using System.Windows;
namespace WPFwithEFSample
{
public partial class MainWindow : Window
{
private ProductContext _context = new ProductContext();
public MainWindow()
{
InitializeComponent();
}
_context.SaveChanges();
// Refresh the grids so the database generated values show
up.
this.categoryDataGrid.Items.Refresh();
this.productsDataGrid.Items.Refresh();
}
Enter a category name in the top grid and product names in the bottom grid Do
not enter anything in ID columns, because the primary key is generated by the
database
Press the Save button to save the data to the database
After the call to DbContext’s SaveChanges(), the IDs are populated with the database
generated values. Because we called Refresh() after SaveChanges() the DataGrid
controls are updated with the new values as well.
Additional Resources
To learn more about data binding to collections using WPF, see this topic in the WPF
documentation.