Jegyzet
Az oldalhoz való hozzáférés engedélyezést igényel. Próbálhatod be jelentkezni vagy könyvtárat váltani.
Az oldalhoz való hozzáférés engedélyezést igényel. Megpróbálhatod a könyvtár váltását.
Ez a lépésről-lépésre útmutató bemutatja, hogyan kötheti a POCO-típusokat a WPF-vezérlőkhöz egy "mester-részlet" elrendezésben. Az alkalmazás az Entity Framework API-kkal tölti fel az objektumokat az adatbázisból származó adatokkal, nyomon követi a változásokat, és megőrzi az adatokat az adatbázisban.
A modell két típust határoz meg, amelyek egy-a-többhöz kapcsolatban vesznek részt: Kategória (fő\alap) és Termék (függő\részlet). A WPF adatkötési keretrendszere lehetővé teszi a kapcsolódó objektumok közötti navigálást: a fő nézetben lévő sorok kijelölése miatt a részletnézet frissül a megfelelő gyermekadatokkal.
Az útmutatóban szereplő képernyőképek és kódrészletek a Visual Studio 2019 16.6.5-ös verzióból származnak.
Tip
A cikk mintáját a GitHubtekintheti meg.
Pre-Requisites
Az útmutató elvégzéséhez telepítenie kell a Visual Studio 2019 16.3 vagy újabb verzióját a .NET asztali fejlesztési munkaterheléssel. A Visual Studio legújabb verziójának telepítéséről további információt a Visual Studio telepítése című témakörben talál.
Az alkalmazás létrehozása
- A Visual Studio megnyitása
- A kezdési ablakban válassza az Új projekt létrehozása lehetőséget.
- Keressen rá a "WPF" kifejezésre, válassza a WPF-alkalmazás (.NET), majd a Tovább gombot.
- A következő képernyőn adjon nevet a projektnek, például GetStartedWPF néven, és válassza a Létrehozás lehetőséget.
Az Entity Framework NuGet-csomagok telepítése
Kattintson a jobb gombbal a megoldásra, és válassza a NuGet-csomagok kezelése megoldás szintjén...
Írja be
entityframeworkcore.sqlitea keresőmezőbe.Válassza ki a Microsoft.EntityFrameworkCore.Sqlite csomagot.
Ellenőrizze a projektet a jobb oldali panelen, és kattintson a Telepítés gombra
Ismételje meg a lépéseket a
entityframeworkcore.proxieskereséséhez és telepítéséhez.
Note
Az Sqlite-csomag telepítésekor automatikusan lekérte a kapcsolódó Microsoft.EntityFrameworkCore alapcsomagot. A Microsoft.EntityFrameworkCore.Proxies csomag támogatja a "lazy-loading" adatokat. Ez azt jelenti, hogy ha gyermekentitással rendelkező entitásokkal rendelkezik, a rendszer csak a szülőket kéri le a kezdeti terhelésre. A proxyk észlelik, ha megkísérlik elérni a gyermek entitásokat, és automatikusan betöltik őket igény szerint.
Modell definiálása
Ebben az útmutatóban egy modellt fog implementálni az "első kód" használatával. Ez azt jelenti, hogy az EF Core az Ön által definiált C#-osztályok alapján hozza létre az adatbázistáblákat és -sémákat.
Adjon hozzá egy új osztályt. Adja meg a nevet: Product.cs és töltse ki a következőképpen:
Product.cs
namespace GetStartedWPF
{
public class Product
{
public int ProductId { get; set; }
public string Name { get; set; }
public int CategoryId { get; set; }
public virtual Category Category { get; set; }
}
}
Ezután adjon hozzá egy elnevezett Category.cs osztályt, és töltse fel a következő kóddal:
Category.cs
using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace GetStartedWPF
{
public class Category
{
public int CategoryId { get; set; }
public string Name { get; set; }
public virtual ICollection<Product>
Products
{ get; private set; } =
new ObservableCollection<Product>();
}
}
A Kategória osztály Termékek tulajdonsága és a Termék osztály Kategória tulajdonsága navigációs tulajdonságok. Az Entity Frameworkben a navigációs tulajdonságok lehetővé teszik a két entitástípus közötti kapcsolatok közötti navigálást.
Az entitások definiálása mellett meg kell határoznia egy olyan osztályt, amely a DbContextből származik, és elérhetővé teszi a DbSet<TEntity> tulajdonságait. A DbSet<TEntity> tulajdonságai tudatják a környezettel, hogy mely típusokat szeretné belefoglalni a modellbe.
A DbContext származtatott típus egy példánya a futtatás során kezeli az entitásobjektumokat, amely magában foglalja az adatbázisokból származó adatokkal rendelkező objektumok feltöltését, a változáskövetést és az adatok adatbázisba való megőrzését.
Adjon hozzá egy új ProductContext.cs osztályt a projekthez a következő definícióval:
ProductContext.cs
using Microsoft.EntityFrameworkCore;
namespace GetStartedWPF
{
public class ProductContext : DbContext
{
public DbSet<Product> Products { get; set; }
public DbSet<Category> Categories { get; set; }
protected override void OnConfiguring(
DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlite(
"Data Source=products.db");
optionsBuilder.UseLazyLoadingProxies();
}
}
}
- A
DbSetrendszer tájékoztatja az EF Core-t arról, hogy milyen C#-entitásokat kell az adatbázishoz leképezni. - Az EF Core
DbContextkonfigurálásának számos módja van. Ezekről a következő témakörben olvashat: DbContext konfigurálása. - Ez a példa a
OnConfiguringfelülbírálást használja egy Sqlite-adatfájl megadásához. - A
UseLazyLoadingProxieshívás arra utasítja az EF Core-t, hogy hajtsa végre a késleltetett betöltést, így automatikusan betölti a gyermek entitásokat, amikor a szülőről fér hozzájuk.
A projekt fordításához nyomja le a CTRL+SHIFT+B billentyűkombinációt, vagy lépjen a Megoldás felépítése > parancsra.
Tip
További információ az adatbázis és az EF Core-modellek szinkronban tartásáról: Az adatbázisséma kezelése.
lusta betöltés
A Kategória osztály Termékek tulajdonsága és a Termék osztály Kategória tulajdonsága navigációs tulajdonságok. Az Entity Framework Core-ban a navigációs tulajdonságok lehetővé teszik a két entitástípus közötti kapcsolatok közötti navigálást.
Az EF Core lehetővé teszi a kapcsolódó entitások automatikus betöltését az adatbázisból a navigációs tulajdonság első elérésekor. Az ilyen típusú (lusta betöltés) esetén vegye figyelembe, hogy az egyes navigációs tulajdonságok első elérésekor egy külön lekérdezés lesz végrehajtva az adatbázison, ha a tartalom még nem szerepel a környezetben.
A "Plain Old C# Object" (POCO) entitástípusok használatakor az EF Core lusta betöltést ér el azáltal, hogy futásidőben létrehoz egy származtatott proxytípust, majd felülírja a virtuális tulajdonságokat az osztályokban, így hozzáadva a betöltési hívást. A kapcsolódó objektumok lusta betöltéséhez a navigációs tulajdonság gettereit nyilvánosként és virtuálisként kell deklarálnia (Visual Basicben felülírhatóként), és az osztály nem lehet zárt (Visual Basicben nem felülírható). A Database First használatakor a navigációs tulajdonságok automatikusan virtuálissá válnak a késleltetett betöltés engedélyezése érdekében.
Objektum kötése vezérlőkhöz
Adja hozzá a modellben definiált osztályokat adatforrásként ehhez a WPF-alkalmazáshoz.
Kattintson duplán a MainWindow.xaml elemre a Megoldáskezelőben a főűrlap megnyitásához
Az XAML szerkesztéséhez válassza az XAML lapot.
Közvetlenül a nyitó
Windowcímke után adja hozzá a következő forrásokat az EF Core-entitásokhoz való csatlakozáshoz.<Window x:Class="GetStartedWPF.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:GetStartedWPF" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800" Loaded="Window_Loaded"> <Window.Resources> <CollectionViewSource x:Key="categoryViewSource"/> <CollectionViewSource x:Key="categoryProductsViewSource" Source="{Binding Products, Source={StaticResource categoryViewSource}}"/> </Window.Resources>Ez beállítja a forrást a "szülő" kategóriákhoz, a második forrásként szolgál pedig a "részletes" termékekhez.
Ezután adja hozzá az alábbi korrektúrát az XAML-hez a nyitó
Gridcímke után.<DataGrid x:Name="categoryDataGrid" AutoGenerateColumns="False" EnableRowVirtualization="True" ItemsSource="{Binding Source={StaticResource categoryViewSource}}" Margin="13,13,43,229" RowDetailsVisibilityMode="VisibleWhenSelected"> <DataGrid.Columns> <DataGridTextColumn Binding="{Binding CategoryId}" Header="Category Id" Width="SizeToHeader" IsReadOnly="True"/> <DataGridTextColumn Binding="{Binding Name}" Header="Name" Width="*"/> </DataGrid.Columns> </DataGrid>Ne feledje, hogy a
CategoryIdazért vanReadOnlybeállítva, mert azt az adatbázis rendeli hozzá, és nem módosítható.
Részletek táblázatának hozzáadása
Most, hogy a keret már létezik a kategóriák megjelenítéséhez, hozzá lehet adni a részletek keretet, hogy megjelenítse a termékeket. Adja hozzá ezt az Grid elemhez a kategóriák DataGrid elem után.
MainWindow.xaml
<DataGrid x:Name="productsDataGrid" AutoGenerateColumns="False"
EnableRowVirtualization="True"
ItemsSource="{Binding Source={StaticResource categoryProductsViewSource}}"
Margin="13,205,43,108" RowDetailsVisibilityMode="VisibleWhenSelected"
RenderTransformOrigin="0.488,0.251">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding CategoryId}"
Header="Category Id" Width="SizeToHeader"
IsReadOnly="True"/>
<DataGridTextColumn Binding="{Binding ProductId}" Header="Product Id"
Width="SizeToHeader" IsReadOnly="True"/>
<DataGridTextColumn Binding="{Binding Name}" Header="Name" Width="*"/>
</DataGrid.Columns>
</DataGrid>
Végül adjon hozzá egy Save gombot és egy vezetéket a kattintási eseményhez Button_Click.
<Button Content="Save" HorizontalAlignment="Center" Margin="0,240,0,0"
Click="Button_Click" Height="20" Width="123"/>
A tervező nézetnek így kell kinéznie:
Adatkapcsolatot kezelő kód hozzáadása
Itt az ideje, hogy néhány eseménykezelőt hozzáadjon a főablakhoz.
Az XAML ablakban kattintson az <Ablak> elemre a főablak kijelöléséhez.
A Tulajdonságok ablakban válassza a jobb felső sarokban lévő Események lehetőséget, majd kattintson duplán a betöltött címke jobb oldalán található szövegdobozra.
Ezzel elérhetővé tesszük az űrlap mögötti kódot, és most szerkesztjük a kódot az ProductContext adathozzáférés végrehajtásához. Frissítse a kódot az alább látható módon.
A kód egy hosszú ideig futó példányt ProductContextdeklarál. Az ProductContext objektum az adatok lekérdezésére és az adatbázisba való mentésére szolgál. A Dispose() példányon lévő ProductContext metódus ezután a felülírt OnClosing metódusból kerül meghívásra. A kód megjegyzései ismertetik az egyes lépések célját.
MainWindow.xaml.cs
using Microsoft.EntityFrameworkCore;
using System.ComponentModel;
using System.Windows;
using System.Windows.Data;
namespace GetStartedWPF
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private readonly ProductContext _context =
new ProductContext();
private CollectionViewSource categoryViewSource;
public MainWindow()
{
InitializeComponent();
categoryViewSource =
(CollectionViewSource)FindResource(nameof(categoryViewSource));
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
// this is for demo purposes only, to make it easier
// to get up and running
_context.Database.EnsureCreated();
// load the entities into EF Core
_context.Categories.Load();
// bind to the source
categoryViewSource.Source =
_context.Categories.Local.ToObservableCollection();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
// all changes are automatically tracked, including
// deletes!
_context.SaveChanges();
// this forces the grid to refresh to latest values
categoryDataGrid.Items.Refresh();
productsDataGrid.Items.Refresh();
}
protected override void OnClosing(CancelEventArgs e)
{
// clean up database connections
_context.Dispose();
base.OnClosing(e);
}
}
}
Note
A kód egy hívással EnsureCreated() hozza létre az adatbázist az első futtatáskor. Ez a demók esetében elfogadható, az éles alkalmazásokban azonban a séma kezeléséhez érdemes megfontolnia a migrációkat. A kód szinkron módon is fut, mert helyi SQLite-adatbázist használ. A típikusan távoli kiszolgálót érintő éles forgatókönyvek esetén fontolja meg az Load és SaveChanges metódusok aszinkron verzióinak használatát.
A WPF-alkalmazás tesztelése
Fordítsa le és futtassa az alkalmazást az F5 billentyű lenyomásával vagy a Hibakeresés > indítása hibakeresés lehetőség választásával. Az adatbázist automatikusan létre kell hozni egy nevű products.dbfájllal. Adjon meg egy kategórianevet, és nyomja le az Enter billentyűt, majd adja hozzá a termékeket az alsó rácshoz. Kattintson a Mentés gombra, és figyelje meg a rács frissítését az adatbázis megadott azonosítóival. A sor eltávolításához jelölje ki a sort, és nyomja le a Delete billentyűt . Az entitás a Mentés gombra kattintva törlődik.
Tulajdonságmódosítási értesítés
Ez a példa négy lépésre támaszkodik az entitások felhasználói felülettel való szinkronizálásához.
- A kezdeti hívás
_context.Categories.Load()betölti a kategóriák adatait. - A késleltetett betöltésű proxy betölti a kapcsolódó termékek adatait.
- Az EF Core beépített változáskövetése módosítja az entitásokat, amikor a
_context.SaveChanges()meghívásra kerül, beleértve a beszúrásokat és a törléseket. - A
DataGridView.Items.Refresh()hívások kényszerítik az újonnan létrehozott azonosítókkal való újratöltést.
Ez az első lépések mintájára működik, de más forgatókönyvekhez további kódra lehet szükség. A WPF-vezérlők az entitások mezőinek és tulajdonságainak beolvasásával jelenítik meg a felhasználói felületet. Amikor szerkeszt egy értéket a felhasználói felületen (UI), a rendszer átadja az értéket az entitásnak. Ha egy tulajdonság értékét közvetlenül az entitáson módosítja, például betölti az adatbázisból, a WPF nem tükrözi azonnal a felhasználói felületen megjelenő változásokat. A renderelő motort értesíteni kell a változásokról. A projekt ezt úgy valósította meg, hogy manuálisan hívta meg a Refresh(). Az értesítés automatizálásának egyszerű módja az INotifyPropertyChanged felület implementálása. A WPF-összetevők automatikusan észlelik a felületet, és regisztrálnak a változási eseményekre. Az entitás felelős ezeknek az eseményeknek a keltéséért.
Tip
Ha többet szeretne megtudni a módosítások kezeléséről, olvassa el a következőt: A tulajdonságmódosítási értesítés implementálása.
Következő lépések
További információ a DbContext konfigurálásáról.