This article is about Entity Framework with .Net WPF, Database-First approach. We will make a sample app step by step,
Step 1: Create an ASP.NET WPF application
Step 2: Reverse Engineer Model
Step 2-1, Alternative Approach: Code First
Step 3: Data Binding
Step 4: CURD
At the end, we will have an .Net WPF app that can consume a database directly through entity framework.
Step 1 - Create an ASP.NET WPF app
We use the current version of Visual Studio 2019 16.9.3 and .NET Framework 4.8 to build the app:
Start Visual Studio and select Create a new project.
In the Create a new project dialog, select WPF App (.NET Framework) > Next.
In the Configure your new project dialog, enter WPF_DatabaseFirst for Project name > Create.
Build and run the app, it will be an empty window.
Step 2, Reverse Engineer Model
For this step, whatever WPF or Web app (MVC or Web API or Web Forms), they are all the exactly same. We will skip the procedure and use the result at Step 2, from Article Entity Framework (2), with .Net MVC, Database-First,
Once the reverse engineer process completes the new model is added to the project and opened up for viewing in the Entity Framework Designer:
The created entity class, the entity context and the connection string will be exactly the same as ones in the MVC module, where the Store class is like this:
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace WPF_DatabaseFirst
{
using System;
using System.Collections.Generic;
public partial class store
{
public string stor_id { get; set; }
public string stor_name { get; set; }
public string stor_address { get; set; }
public string city { get; set; }
public string state { get; set; }
public string zip { get; set; }
}
}
the Data Context will be in pubsEntities class:
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace WPF_DatabaseFirst
{
using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
public partial class pubsEntities : DbContext
{
public pubsEntities()
: base("name=pubsEntities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<store> stores { get; set; }
}
}
and the connection details for the database will be inserted into app.config file:
<connectionStrings>
<add name="pubsEntities" connectionString="metadata=res://*/Model1.csdl|res://*/Model1.ssdl|res://*/Model1.msl;provider=System.Data.SqlClient;provider connection string="data source=localhost;
initial catalog=pubs;
integrated security=True;
MultipleActiveResultSets=True;
App=EntityFramework"" providerName="System.Data.EntityClient" />
</connectionStrings>
Step 2-1, Alternative Approach: Code First
In fact, the Code First approach for .NET Framework is quite simple, just using the entity class and context as created above, even the connection string is not necessary, as simple as these: Entity class
namespace WPF_CodeFirst
{
public partial class store
{
public string stor_id { get; set; }
public string stor_name { get; set; }
public string stor_address { get; set; }
public string city { get; set; }
public string state { get; set; }
public string zip { get; set; }
}
}
Context class
namespace WPF_CodeFirst
{
using System.Data.Entity;
public partial class pubsEntities : DbContext
{
public virtual DbSet<store> stores { get; set; }
}
}
build the app, we have the database created automatically. See details from Article Entity Framework (1), with .Net MVC, Code-First,
Step 3 - Data Binding: Build the Grid, and Run the app
From both and either the Database First approach or Code First approach above, we got here for the next step: Data Binding, which is something of WPF different from Web module where we can use Scaffolder tool to build the CRUD (controller) using entity framework automatically.
In fact, for the Visual Studio 2010, our job has been almost done, as I described in my previous article WCF (4), RIA Services, that gave a entity database first approach for building a WPF app:
We already have a DataSource available for Data Binding:
Drag and Drop DataSource into XAML window
Run the app, we got the Data Grid
However, for current Visual Studio, actually, after VS 2010, we need to do a little bit more work:
1, Build a Data Source Object:
From the main menu, select Project => Add New Data Source …(in Visual Studio 2010, select Data => Add New Data Source…)
In the Choose a Data Source Type window, select Object and click Next
In the Select the Data Objects dialog, unfold the application name, here: WPF_DatabaseFirst two times and select data Store => Finish
Now we have the Data Source (open: VS Main menu => View => Other Windows => Data Sources):
2, Build a Grid and link to Data Source:
Drag and Drop DataSource into XAML window, however, we still cannot see the data after running the app:
This is because after dragging and dropping Data Source into Window, the window code behind does not really setup the connection to the data source as VS 2010 did,
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
System.Windows.Data.CollectionViewSource storeViewSource = ((System.Windows.Data.CollectionViewSource)(this.FindResource("storeViewSource")));
// Load data by setting the CollectionViewSource.Source property:
// storeViewSource.Source = [generic data source]
}
}
Create a Context instance, and link the DataView Source to the Data Source:
public partial class MainWindow : Window
{
private pubsEntities _context = new pubsEntities();
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
System.Windows.Data.CollectionViewSource storeViewSource = ((System.Windows.Data.CollectionViewSource)(this.FindResource("storeViewSource")));
_context.stores.Load();
//Load data by setting the CollectionViewSource.Source property:
// storeViewSource.Source = [generic data source]
storeViewSource.Source = _context.stores.Local;
}
}
Now we have the result we want,
Step 4 - CURD
For Web app, after building entity framework, we can use Scaffolder to make CURD happen in controller. Now, we can view data, we need to add CUD: Actually, add a save button in the Window, we can do the job:
From the Toolbox, drag Button on to the form. Set the Content property to Save:
Double Click the button, then add logic into the event handller:
private void button_Click_1(object sender, RoutedEventArgs e)
{
// all changes are automatically tracked, including
// deletes!
_context.SaveChanges();
// this forces the grid to refresh to latest values
storeDataGrid.Items.Refresh();
//productsDataGrid.Items.Refresh();
}
The Save button will do the CUD work:
Summary
The .NET WPF for Database-First approach is much similar to the web app, with a little bit more work. Here, we just discuss the basic concept to use Entity Framework to build a simple data driven app and see the similarity with Web apps, but we did not touch more complex issue for WPF exclusively. For example, for master/details data, the database first approach need to be modify the auto created code, such as using ObservableCollection, instead of ICollection, see here for details. And we did not touch the major features for WPF, such as enforcing INotifyPropertyChanged interface to notice any data changes, The project did this by manually calling Refresh().
Source: Paper.li
The Tech Platform
Comments