Megosztás:


A Windows Forms használatának első lépései

Ez a lépésenkénti útmutató bemutatja, hogyan hozhat létre egy egyszerű, SQLite-adatbázissal támogatott Windows Forms-(WinForms-) alkalmazást. Az alkalmazás az Entity Framework Core (EF Core) használatával tölti be az adatokat az adatbázisból, nyomon követi az adatok módosításait, és megőrzi ezeket a módosításokat az adatbázisba.

Az útmutatóban szereplő képernyőképek és kódrészletek a Visual Studio 2022 17.3.0-s verzióból származnak.

Jótanács

A cikk mintáját a GitHubtekintheti meg.

Előfeltételek

A bemutató befejezéséhez telepítenie kell a Visual Studio 2022 17.3 vagy újabb verzióját a kijelölt .NET desktop környezet mellett. 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. Válassza a Windows Forms appot , majd a Tovább gombot.

    Új Windows Forms-projekt létrehozása

  4. A következő képernyőn adjon nevet a projektnek( például GetStartedWinForms), és válassza a Tovább gombot.

  5. A következő képernyőn válassza ki a használni kívánt .NET-verziót. Ez az útmutató a .NET 7-tel lett létrehozva, de a későbbi verziókkal is működnie kell.

  6. Válassza a Létrehozás elemet.

Az EF Core 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 a projekt számára

  2. Válassza a Tallózás lapot, és keressen rá a "Microsoft.EntityFrameworkCore.Sqlite" kifejezésre.

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

  4. Ellenőrizze a GetStartedWinForms projektet a jobb oldali panelen.

  5. Válassza ki a legújabb verziót. A kiadás előtti verzió használatához győződjön meg arról, hogy az Include prerelease (Előzetes verzió belefoglalása) jelölőnégyzet be van jelölve.

  6. Kattintson a Telepítés gombra

    A Microsoft.EntityFrameworkCore.Sqlite csomag telepítése

Megjegyzés:

A Microsoft.EntityFrameworkCore.Sqlite az EF Core SQLite-adatbázissal való használatához használt "adatbázis-szolgáltató" csomag. Hasonló csomagok érhetők el más adatbázisrendszerekhez is. Az adatbázis-szolgáltatói csomagok telepítése automatikusan biztosítja az EF Core és az adatbázisrendszer használatához szükséges összes függőséget. Ez magában foglalja a Microsoft.EntityFrameworkCore alapcsomagot is.

Modell definiálása

Ebben az útmutatóban a "Code First" használatával implementálunk egy modellt. 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. Az adatbázisséma kezelése című témakörből megtudhatja, hogyan használhat helyette egy meglévő adatbázist.

  1. Kattintson a jobb gombbal a projektre, és válassza a Hozzáadás, majd az Osztály lehetőséget egy új osztály hozzáadásához.

    Új osztály hozzáadása

  2. Használja a fájlnevet Product.cs , és cserélje le az osztály kódját a következőre:

    using System.ComponentModel;
    
    namespace GetStartedWinForms;
    
    public class Product
    {
        public int ProductId { get; set; }
    
        public string? Name { get; set; }
    
        public int CategoryId { get; set; }
        public virtual Category Category { get; set; } = null!;
    }
    
  3. Ismételje meg a létrehozást Category.cs a következő kóddal:

    using Microsoft.EntityFrameworkCore.ChangeTracking;
    
    namespace GetStartedWinForms;
    
    public class Category
    {
        public int CategoryId { get; set; }
    
        public string? Name { get; set; }
    
        public virtual ObservableCollectionListSource<Product> Products { get; } = new();
    }
    

Az Products osztály tulajdonságát Category és az Category osztály tulajdonságát Product "navigációnak" nevezzük. Az EF Core-ban a navigációk két entitástípus közötti kapcsolatot határoznak meg. Ebben az esetben a navigáció arra a Product.Category kategóriára hivatkozik, amelyhez egy adott termék tartozik. Hasonlóképpen, a Category.Products gyűjtemény navigációs sávja egy adott kategóriához tartozó összes terméket tartalmazza.

Jótanács

Windows Forms használata esetén a ObservableCollectionListSource, amely megvalósítja a IListSource-t, használható gyűjteménynavigációkhoz. Ez nem szükséges, de javítja a kétirányú adatkötési élményt.

A DbContext definiálása

Az EF Core-ban a modell entitástípusainak konfigurálására és az adatbázissal való interakció munkamenetként való kezelésére szolgál az EF Core-ban származtatott DbContext osztály. A legegyszerűbb esetben egy DbContext osztály:

  • A modell minden entitástípusának tulajdonságait tartalmazza DbSet .
  • Felülírja a OnConfiguring metódust, amely az adatbázis-szolgáltatót és a kapcsolati sztringet konfigurálja használatra. További információ: DbContext konfigurálása .

Ebben az esetben a DbContext osztály felülbírálja az OnModelCreating alkalmazás néhány mintaadatának megadására szolgáló módszert is.

Adjon hozzá egy új ProductsContext.cs osztályt a projekthez a következő kóddal:

using Microsoft.EntityFrameworkCore;

namespace GetStartedWinForms;

public class ProductsContext : 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");

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Category>().HasData(
            new Category { CategoryId = 1, Name = "Cheese" },
            new Category { CategoryId = 2, Name = "Meat" },
            new Category { CategoryId = 3, Name = "Fish" },
            new Category { CategoryId = 4, Name = "Bread" });

        modelBuilder.Entity<Product>().HasData(
            new Product { ProductId = 1, CategoryId = 1, Name = "Cheddar" },
            new Product { ProductId = 2, CategoryId = 1, Name = "Brie" },
            new Product { ProductId = 3, CategoryId = 1, Name = "Stilton" },
            new Product { ProductId = 4, CategoryId = 1, Name = "Cheshire" },
            new Product { ProductId = 5, CategoryId = 1, Name = "Swiss" },
            new Product { ProductId = 6, CategoryId = 1, Name = "Gruyere" },
            new Product { ProductId = 7, CategoryId = 1, Name = "Colby" },
            new Product { ProductId = 8, CategoryId = 1, Name = "Mozzela" },
            new Product { ProductId = 9, CategoryId = 1, Name = "Ricotta" },
            new Product { ProductId = 10, CategoryId = 1, Name = "Parmesan" },
            new Product { ProductId = 11, CategoryId = 2, Name = "Ham" },
            new Product { ProductId = 12, CategoryId = 2, Name = "Beef" },
            new Product { ProductId = 13, CategoryId = 2, Name = "Chicken" },
            new Product { ProductId = 14, CategoryId = 2, Name = "Turkey" },
            new Product { ProductId = 15, CategoryId = 2, Name = "Prosciutto" },
            new Product { ProductId = 16, CategoryId = 2, Name = "Bacon" },
            new Product { ProductId = 17, CategoryId = 2, Name = "Mutton" },
            new Product { ProductId = 18, CategoryId = 2, Name = "Pastrami" },
            new Product { ProductId = 19, CategoryId = 2, Name = "Hazlet" },
            new Product { ProductId = 20, CategoryId = 2, Name = "Salami" },
            new Product { ProductId = 21, CategoryId = 3, Name = "Salmon" },
            new Product { ProductId = 22, CategoryId = 3, Name = "Tuna" },
            new Product { ProductId = 23, CategoryId = 3, Name = "Mackerel" },
            new Product { ProductId = 24, CategoryId = 4, Name = "Rye" },
            new Product { ProductId = 25, CategoryId = 4, Name = "Wheat" },
            new Product { ProductId = 26, CategoryId = 4, Name = "Brioche" },
            new Product { ProductId = 27, CategoryId = 4, Name = "Naan" },
            new Product { ProductId = 28, CategoryId = 4, Name = "Focaccia" },
            new Product { ProductId = 29, CategoryId = 4, Name = "Malted" },
            new Product { ProductId = 30, CategoryId = 4, Name = "Sourdough" },
            new Product { ProductId = 31, CategoryId = 4, Name = "Corn" },
            new Product { ProductId = 32, CategoryId = 4, Name = "White" },
            new Product { ProductId = 33, CategoryId = 4, Name = "Soda" });
    }
}

Ezen a ponton mindenképpen hozza létre a megoldást .

Vezérlők hozzáadása az űrlaphoz

Az alkalmazás megjeleníti a kategóriák listáját és a termékek listáját. Ha az első listában kiválaszt egy kategóriát, a második lista az adott kategóriához tartozó termékeket jeleníti meg. Ezek a listák módosíthatók termékek és kategóriák hozzáadására, eltávolítására vagy szerkesztésére, és ezek a módosítások a Mentés gombra kattintva menthetők az SQLite-adatbázisba.

  1. Módosítsa a főűrlap nevét a következőre Form1MainForm: .

    Űrlap1 átnevezése MainForm-ra

  2. És módosítsa a címet "Termékek és kategóriák" értékre.

    Cím (fő űrlap)

  3. Az Eszközkészlet használatával adjon hozzá két DataGridView vezérlőt egymás mellé rendezve.

    DataGridView hozzáadása

  4. Az első DataGridView között módosítsa a nevet a következőredataGridViewCategories: .

  5. A második tulajdonságok között a DataGridView változtassa meg a Nevet a dataGridViewProducts-re.

  6. Az eszközkészletet is használva adjon hozzá egy vezérlőt Button .

  7. Nevezze el a gombot buttonSave , és adja meg a "Mentés" szöveget. Az űrlapnak a következőképpen kell kinéznie:

    Űrlapelrendezés

Adatkötés

A következő lépés, hogy a modellben található Product és Category típusokat összekapcsoljuk a DataGridView vezérlőkkel. Ez az EF Core által betöltött adatokat a vezérlőkhöz köti, így az EF Core által követett entitások szinkronban maradnak a vezérlőkben megjelenőkkel.

  1. Kattintson a Tervező művelet ikonra az első DataGridView. Ez a vezérlő jobb felső sarkában található apró gomb.

    A tervezői művelet jele

  2. Ekkor megnyílik a műveletlista, amelyből elérhető a kiválasztott adatforrás legördülő listája. Még nem hoztunk létre adatforrást, ezért lépjen az aljára, és válassza az Új objektum adatforrás hozzáadása... lehetőséget.

    Új objektumadatforrás hozzáadása

  3. A Kategória gombra kattintva objektum-adatforrást hozhat létre a kategóriák számára, és kattintson az OK gombra.

    Kategória adatforrástípusának kiválasztása

    Jótanács

    Ha itt nem jelennek meg adatforrástípusok, győződjön meg róla, hogy Product.cs, Category.cs és ProductsContext.cs hozzá lett adva a projekthez és a megoldás le lett fordítva.

  4. Most az Adatforrás kiválasztása legördülő menü tartalmazza az imént létrehozott objektum-adatforrást. Bontsa ki az Egyéb adatforrások, majd a Projekt adatforrások elemet, és válassza a Kategória lehetőséget.

    Kategória adatforrásának kiválasztása

    A második DataGridView termékhez lesz kötve. A felső szintű Product típushoz való kötés helyett azonban inkább az Products első Categorykötésből származó DataGridView navigációhoz lesz kötve. Ez azt jelenti, hogy ha az első nézetben kiválaszt egy kategóriát, az adott kategória termékei automatikusan a második nézetben lesznek használatban.

  5. A második elemnél a DataGridView használva válassza az Adatforrás kiválasztása lehetőséget, majd bontsa ki a categoryBindingSource elemet, és válassza a Products lehetőséget.

    Termékek adatforrás kiválasztása

A megjelenített adatok konfigurálása

Alapértelmezés szerint a kötött típusok minden tulajdonságához létrejön egy oszlop a DataGridView-ben. Ezen tulajdonságok értékeit is szerkesztheti a felhasználó. Egyes értékek, például az elsődleges kulcsértékek azonban elméletileg csak olvashatók, ezért nem szerkeszthetők. Emellett egyes tulajdonságok, például az CategoryId idegenkulcs-tulajdonság és a Category navigáció nem hasznosak a felhasználó számára, ezért rejtve kell lenniük.

Jótanács

Gyakori, hogy egy valós alkalmazásban elrejti az elsődleges kulcstulajdonságokat. Itt láthatóak maradnak, hogy könnyen láthatóvá tegyék, hogy az EF Core mit csinál a színfalak mögött.

  1. Kattintson a jobb gombbal az elsőre DataGridView , és válassza az Oszlopok szerkesztése... parancsot.

    DataGridView-oszlopok szerkesztése

  2. Állítsa be az CategoryId oszlopot, amely az elsődleges kulcsot ábrázolja, írásvédetté, majd kattintson az OK gombra.

    CategoryId oszlop írásvédetté tétele

  3. Kattintson a jobb gombbal a második DataGridView elemre, és válassza az Oszlopok szerkesztése... parancsot. Tegye a ProductId oszlopot írásvédetté, távolítsa el a CategoryId és a Category oszlopokat, majd kattintson az OK gombra.

    ProductId oszlop írásvédetté tétele és CategoryId és Kategória oszlopok eltávolítása

Csatlakozás az EF Core-hoz

Az alkalmazásnak most már kis mennyiségű kódra van szüksége az EF Core adatkötött vezérlőkhöz való csatlakoztatásához.

  1. MainForm A kód megnyitásához kattintson a jobb gombbal a fájlra, és válassza a Kód megtekintése parancsot.

    Kód megtekintése

  2. Adjon hozzá egy privát mezőt a DbContext munkamenet tárolásához, és adjon hozzá felülbírálásokat a OnLoad és OnClosing metódusokhoz. A kódnak így kell kinéznie:

using Microsoft.EntityFrameworkCore;
using System.ComponentModel;

namespace GetStartedWinForms
{
    public partial class MainForm : Form
    {
        private ProductsContext? dbContext;

        public MainForm()
        {
            InitializeComponent();
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            this.dbContext = new ProductsContext();

            // Uncomment the line below to start fresh with a new database.
            // this.dbContext.Database.EnsureDeleted();
            this.dbContext.Database.EnsureCreated();

            this.dbContext.Categories.Load();

            this.categoryBindingSource.DataSource = dbContext.Categories.Local.ToBindingList();
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            base.OnClosing(e);

            this.dbContext?.Dispose();
            this.dbContext = null;
        }
    }
}

A OnLoad metódus meghívása az űrlap betöltésekor történik. Jelenleg

  • Létrejön egy ProductsContext példány, amely az alkalmazás által megjelenített termékek és kategóriák betöltésére és változásainak nyomon követésére szolgál.
  • EnsureCreated A DbContext meghívásával hozza létre az SQLite-adatbázist, ha még nem létezik. Ez egy gyors módja annak, hogy adatbázist hozzon létre alkalmazások prototípusának vagy tesztelésének során. Ha azonban a modell megváltozik, az adatbázist törölni kell, hogy újra létre lehessen hozni. (A EnsureDeleted sor megjegyzés nélkül is törölhető, így egyszerűen törölheti és újra létrehozhatja az adatbázist az alkalmazás futtatásakor.) Ehelyett az EF Core Migrations használatával módosíthatja és frissítheti az adatbázissémát anélkül, hogy adatokat veszítené el.
  • EnsureCreated az új adatbázist is feltölti a metódusban ProductsContext.OnModelCreating meghatározott adatokkal.
  • A Load bővítménymetódus az adatbázis összes kategóriájának betöltésére szolgál a DbContext. Ezeket az entitásokat mostantól nyomon követi a DbContextrendszer, amely észleli a kategóriák felhasználó általi szerkesztésekor végrehajtott módosításokat.
  • A categoryBindingSource.DataSource tulajdonság inicializálva lesz azokhoz a kategóriákhoz, amelyeket a DbContextrendszer nyomon követ. Ez úgy történik, hogy a Local.ToBindingList()Categories tulajdonságon meghívjuk a DbSet-t. Local hozzáférést biztosít a nyomon követett kategóriák helyi nézetéhez, és az események összekapcsolva biztosítják, hogy a helyi adatok szinkronban legyenek a megjelenített adatokkal, és fordítva. ToBindingList() ezeket az adatokat úgy teszi elérhetővé, mint egy IBindingList, amelyet a Windows Forms adatkötés értelmez.

A OnClosing metódus meghívása az űrlap bezárásakor történik. A folyamat során a DbContext erőforrások elengedésére kerül sor, biztosítva, hogy minden adatbázis-erőforrás felszabaduljon, és a dbContext mező null értéket kap, hogy az ne legyen újból használható.

A Termékek nézet feltöltése

Ha az alkalmazás ezen a ponton indul el, akkor a következőhöz hasonlóan kell kinéznie:

Az alkalmazás első futtatása

Figyelje meg, hogy a kategóriák be lettek töltve az adatbázisból, de a terméktábla üres marad. A Mentés gomb szintén nem működik.

A termékek táblájának feltöltéséhez az EF Core-nak be kell töltenie a termékeket a kiválasztott kategória adatbázisából. Ennek eléréséhez:

  1. A főűrlap tervezőjében válassza ki a DataGridView kategóriákat.

  2. A TulajdonságokDataGridViewterületen válassza ki az eseményeket (a villám gombot), majd kattintson duplán a SelectionChanged eseményre.

    A SelectionChanged esemény hozzáadása

    Ez létrehoz egy csonkot a fő űrlapkódban ahhoz, hogy egy esemény aktiválódjon, amikor a kategóriaválasztás megváltozik.

  3. Töltse ki az esemény kódját:

private void dataGridViewCategories_SelectionChanged(object sender, EventArgs e)
{
    if (this.dbContext != null)
    {
        var category = (Category)this.dataGridViewCategories.CurrentRow.DataBoundItem;

        if (category != null)
        {
            this.dbContext.Entry(category).Collection(e => e.Products).Load();
        }
    }
}

Ebben a kódban, ha egy aktív (nem null) DbContext munkamenet van, akkor lekérjük a Category példányt, amely a jelenleg kiválasztott DataViewGrid sorhoz van kötve. (Ez akkor fordulhat null elő, ha a nézetben az utolsó sor van kijelölve, amely új kategóriák létrehozására szolgál.) Ha van egy kijelölt kategória, akkor a DbContext felhasználónak be kell töltenie az adott kategóriához társított termékeket. Ezt a következő módon végezheti el:

  • Példány lekérése EntityEntryCategory (dbContext.Entry(category))
  • Tudatni az EF Core-sal, hogy a Products gyűjtemény navigációs sávján szeretnénk Category működni (.Collection(e => e.Products))
  • Végül pedig azt mondja az EF Core-nak, hogy be szeretnénk tölteni az adatbázisból származó termékgyűjteményt (.Load();)

Jótanács

Amikor Load meghívásra kerül, az EF Core csak akkor fér hozzá az adatbázishoz a termékek betöltéséhez, ha azok még nem lettek betöltve.

Ha az alkalmazás most újra fut, akkor a megfelelő termékeket kell betöltenie, amikor kiválaszt egy kategóriát:

A termékek betöltődnek

Módosítások mentése

Végül a Mentés gomb csatlakoztatható az EF Core-hoz, hogy a termékeken és kategóriákon végzett módosítások az adatbázisba legyenek mentve.

  1. A főűrlap tervezőjében válassza a Mentés gombot.

  2. A TulajdonságokButtonterületen válassza ki az eseményeket (a villám gombot), és kattintson duplán a Kattintás eseményre.

    Kattintási esemény hozzáadása mentéshez

  3. Töltse ki az esemény kódját:

private void buttonSave_Click(object sender, EventArgs e)
{
    this.dbContext!.SaveChanges();

    this.dataGridViewCategories.Refresh();
    this.dataGridViewProducts.Refresh();
}

Ez a kód meghívja SaveChanges a DbContextkódot, amely menti az SQLite-adatbázis módosításait. Ha nem történt módosítás, akkor ez egy no-op, és nem történik adatbázis-hívás. A mentés után a DataGridView vezérlők frissülnek. Ennek az az oka, hogy az EF Core beolvassa a létrehozott elsődleges kulcsértékeket az adatbázisból származó új termékekhez és kategóriákhoz. A hívás Refresh frissíti a megjelenítést ezekkel a létrehozott értékekkel.

A végleges alkalmazás

Itt található a fő űrlap teljes kódja:

using Microsoft.EntityFrameworkCore;
using System.ComponentModel;

namespace GetStartedWinForms
{
    public partial class MainForm : Form
    {
        private ProductsContext? dbContext;

        public MainForm()
        {
            InitializeComponent();
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            this.dbContext = new ProductsContext();

            // Uncomment the line below to start fresh with a new database.
            // this.dbContext.Database.EnsureDeleted();
            this.dbContext.Database.EnsureCreated();

            this.dbContext.Categories.Load();

            this.categoryBindingSource.DataSource = dbContext.Categories.Local.ToBindingList();
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            base.OnClosing(e);

            this.dbContext?.Dispose();
            this.dbContext = null;
        }

        private void dataGridViewCategories_SelectionChanged(object sender, EventArgs e)
        {
            if (this.dbContext != null)
            {
                var category = (Category)this.dataGridViewCategories.CurrentRow.DataBoundItem;

                if (category != null)
                {
                    this.dbContext.Entry(category).Collection(e => e.Products).Load();
                }
            }
        }

        private void buttonSave_Click(object sender, EventArgs e)
        {
            this.dbContext!.SaveChanges();

            this.dataGridViewCategories.Refresh();
            this.dataGridViewProducts.Refresh();
        }
    }
}

Az alkalmazás most már futtatható, és a termékek és kategóriák hozzáadhatók, törölhetők és szerkeszthetők. Figyelje meg, hogy ha az alkalmazás bezárása előtt a Mentés gombra kattint, az alkalmazás újrakezdésekor a rendszer az adatbázisban tárolja a módosításokat, és újra betölti őket. Ha a Mentés gombra nem kattint, a módosítások elvesznek az alkalmazás újrakezdésekor.

Jótanács

Új kategória vagy termék hozzáadható a DataViewControl vezérlőelem alján lévő üres sor használatával. A sorokat a Del billentyűt lenyomva lehet törölni.

Mentés előtt

A futó alkalmazás a Mentés gombra kattintás előtt

Mentés után

A futó alkalmazás a Mentés gombra kattintás után

Figyelje meg, hogy a hozzáadott kategória és termékek elsődleges kulcsértékei a Mentés gombra kattintáskor lesznek feltöltve.

Tudj meg többet