Megosztás:


A WPF használatának első lépései

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

  1. A Visual Studio megnyitása
  2. A kezdési ablakban válassza az Új projekt létrehozása lehetőséget.
  3. Keressen rá a "WPF" kifejezésre, válassza a WPF-alkalmazás (.NET), majd a Tovább gombot.
  4. 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

  1. Kattintson a jobb gombbal a megoldásra, és válassza a NuGet-csomagok kezelése megoldás szintjén...

    NuGet-csomagok kezelése

  2. Írja be entityframeworkcore.sqlite a keresőmezőbe.

  3. Válassza ki a Microsoft.EntityFrameworkCore.Sqlite csomagot.

  4. Ellenőrizze a projektet a jobb oldali panelen, és kattintson a Telepítés gombra

    Sqlite-csomag

  5. Ismételje meg a lépéseket a entityframeworkcore.proxies keresé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 DbSet rendszer 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 OnConfiguring felülbírálást használja egy Sqlite-adatfájl megadásához.
  • A UseLazyLoadingProxies hí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.

  1. Kattintson duplán a MainWindow.xaml elemre a Megoldáskezelőben a főűrlap megnyitásához

  2. Az XAML szerkesztéséhez válassza az XAML lapot.

  3. Közvetlenül a nyitó Window cí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>
    
  4. 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.

  5. Ezután adja hozzá az alábbi korrektúrát az XAML-hez a nyitó Grid cí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>
    
  6. Ne feledje, hogy a CategoryId azért van ReadOnly beá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:

A WPF Designer képernyőképe

Adatkapcsolatot kezelő kód hozzáadása

Itt az ideje, hogy néhány eseménykezelőt hozzáadjon a főablakhoz.

  1. Az XAML ablakban kattintson az <Ablak> elemre a főablak kijelöléséhez.

  2. 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.

    Főablak tulajdonságai

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.

Alkalmazás futtatása

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.

  1. A kezdeti hívás _context.Categories.Load() betölti a kategóriák adatait.
  2. A késleltetett betöltésű proxy betölti a kapcsolódó termékek adatait.
  3. 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.
  4. 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.