WPF Kullanmaya Başlarken

Bu adım adım izlenecek yol, POCO türlerini WPF denetimlerine "main-detail" biçiminde bağlamayı gösterir. Uygulama, veritabanındaki verilerle nesneleri doldurmak, değişiklikleri izlemek ve verileri veritabanında kalıcı hale getirmek için Entity Framework API'lerini kullanır.

Model, bire çok ilişkisine katılan iki tür tanımlar: Kategori (asıl\ana) ve Ürün (bağımlı\ayrıntı). WPF veri bağlama çerçevesi, ilgili nesneler arasında gezintiyi etkinleştirir: ana görünümde satırların seçilmesi, ayrıntı görünümünün ilgili alt verilerle güncelleştirilmesine neden olur.

Bu kılavuzdaki ekran görüntüleri ve kod listeleri Visual Studio 2019 16.6.5'ten alınmıştır.

Bahşiş

Bu makalenin örneğini GitHub'da görüntüleyebilirsiniz.

Önkoşullar

Bu kılavuzu tamamlamak için Visual Studio 2019 16.3 veya üzerini .NET masaüstü iş yükü seçili olarak yüklemeniz gerekir. Visual Studio'nun en son sürümünü yükleme hakkında daha fazla bilgi için bkz . Visual Studio'yu Yükleme.

Uygulamayı Oluşturma

  1. Visual Studio’yu açın
  2. Başlangıç penceresinde Yeni proje oluştur'u seçin.
  3. "WPF" araması yapın, WPF Uygulaması (.NET Core) öğesini ve ardından İleri'yi seçin.
  4. Sonraki ekranda projeye getStartedWPF gibi bir ad verin ve Oluştur'u seçin.

Entity Framework NuGet paketlerini yükleme

  1. Çözüme sağ tıklayın ve Çözüm için NuGet Paketlerini Yönet... seçeneğini belirleyin .

    Manage NuGet Packages

  2. Arama kutusuna yazın entityframeworkcore.sqlite .

  3. Microsoft.EntityFrameworkCore.Sqlite paketini seçin.

  4. Sağ bölmede projeyi denetleyin ve Yükle'ye tıklayın

    Sqlite Package

  5. Microsoft.EntityFrameworkCore.Proxies araması yapmak ve yüklemek için entityframeworkcore.proxies adımları yineleyin.

Dekont

Sqlite paketini yüklediğinizde ilgili Microsoft.EntityFrameworkCore temel paketini otomatik olarak aşağı çekti. Microsoft.EntityFrameworkCore.Proxies paketi "gecikmeli yükleme" verileri için destek sağlar. Bu, alt varlıklara sahip varlıklarınız olduğunda ilk yükte yalnızca üst öğeler getirilir anlamına gelir. Proxy'ler alt varlıklara erişme girişiminde bulunulup yapılmaz ve bunları isteğe bağlı olarak otomatik olarak yükler.

Model Tanımlama

Bu kılavuzda "önce kod" kullanarak bir model uygulayacaksınız. Bu, EF Core'un tanımladığınız C# sınıflarını temel alan veritabanı tablolarını ve şemasını oluşturacağı anlamına gelir.

Yeni bir sınıf ekleyin. Adı verin: Product.cs ve şu şekilde doldurun:

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; }
    }
}

Ardından adlı Category.cs bir sınıf ekleyin ve aşağıdaki kodla doldurun:

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>();
    }
}

Category sınıfındaki Products özelliği ve Product sınıfındaki Category özelliği gezinti özellikleridir. Entity Framework'te gezinti özellikleri, iki varlık türü arasındaki ilişkide gezinmek için bir yol sağlar.

Varlıkları tanımlamaya ek olarak, DbContext'ten türetilen ve DbSet<TEntity> özelliklerini kullanıma sunan bir sınıf tanımlamanız gerekir. DbSet<TEntity> özellikleri, bağlama modele hangi türleri eklemek istediğinizi bildirir.

DbContext türetilmiş türünün bir örneği, çalışma zamanında varlık nesnelerini yönetir. Bu, nesneleri veritabanındaki verilerle doldurma, değişiklik izleme ve verileri veritabanında kalıcı hale getirme gibi işlemleri içerir.

Aşağıdaki tanım ile projeye yeni ProductContext.cs bir sınıf ekleyin:

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();
        }
    }
}
  • , EF Core'a DbSet hangi C# varlıklarının veritabanına eşlenmesi gerektiğini bildirir.
  • EF Core'un DbContextyapılandırılmasının çeşitli yolları vardır. Bunlar hakkında bilgi edinmek için bkz. DbContext yapılandırma.
  • Bu örnekte sqlite veri dosyası belirtmek için geçersiz kılma kullanılır OnConfiguring .
  • UseLazyLoadingProxies Çağrısı EF Core'a gecikmeli yükleme gerçekleştirmesini bildirir, bu nedenle üst öğeden erişildiğinde alt varlıklar otomatik olarak yüklenir.

Projeyi derlemek için CTRL+SHIFT+B tuşlarına basın veya Derleme Çözümü Oluştur'a > gidin.

Bahşiş

Veritabanınızı ve EF Core modellerinizi eşitlenmiş durumda tutmanın farklı olduğunu öğrenin: Veritabanı Şemalarını Yönetme.

Geç Yükleme

Category sınıfındaki Products özelliği ve Product sınıfındaki Category özelliği gezinti özellikleridir. Entity Framework Core'da gezinti özellikleri, iki varlık türü arasındaki ilişkide gezinmek için bir yol sağlar.

EF Core, gezinti özelliğine ilk kez erişişiniz için veritabanından ilgili varlıkları otomatik olarak yükleme seçeneği sunar. Bu yükleme türüyle (gecikmeli yükleme olarak adlandırılır), her gezinti özelliğine ilk kez erişişinizde, içerik henüz bağlamda değilse veritabanında ayrı bir sorgu yürütüleceğini unutmayın.

"Düz Eski C# Nesnesi" (POCO) varlık türlerini kullanırken, EF Core çalışma zamanı sırasında türetilmiş ara sunucu türlerinin örneklerini oluşturarak ve ardından yükleme kancasını eklemek için sınıflarınızdaki sanal özellikleri geçersiz kılarak gecikmeli yükleme sağlar. İlgili nesnelerin yavaş yüklenmesini sağlamak için, gezinti özelliği alıcılarını genel ve sanal (Visual Basic'te Geçersiz Kılınabilir) olarak bildirmeniz ve sınıfınızın korumalı olmaması gerekir (Visual Basic'te NotOverridable). Önce Veritabanı kullanılırken, gezinme özellikleri gecikmeli yüklemeyi etkinleştirmek için otomatik olarak sanal hale getirilir.

Nesneyi Denetimlere Bağlama

Modelde tanımlanan sınıfları bu WPF uygulaması için veri kaynakları olarak ekleyin.

  1. Ana formu açmak için Çözüm Gezgini mainWindow.xaml öğesine çift tıklayın

  2. XAML'yi düzenlemek için XAML sekmesini seçin.

  3. Etiketi açtıktan Window hemen sonra EF Core varlıklarına bağlanmak için aşağıdaki kaynakları ekleyin.

    <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. Bu, "üst" kategoriler için kaynak ve "ayrıntı" ürünleri için ikinci kaynak ayarlar.

  5. Ardından, açma Grid etiketinden sonra XAML'nize aşağıdaki işaretlemeyi ekleyin.

    <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. CategoryId veritabanı tarafından atandığından ve değiştirilemediğinden öğesinin olarak ayarlandığını ReadOnly unutmayın.

Ayrıntılar Kılavuzu Ekleme

Kategorileri görüntülemek için kılavuz mevcut olduğuna göre, ayrıntılar kılavuzu ürünleri göstermek için eklenebilir. Bunu, kategoriler DataGrid öğesinin Grid arkasına öğesinin içine ekleyin.

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>

Son olarak, tıklama olayına Button_Clickbir Save düğme ve kablo ekleyin.

<Button Content="Save" HorizontalAlignment="Center" Margin="0,240,0,0" 
        Click="Button_Click" Height="20" Width="123"/>

Tasarım görünümünüz şu şekilde görünmelidir:

Screenshot of WPF Designer

Veri Etkileşimlerini İşleyen Kod Ekleme

Ana pencereye bazı olay işleyicileri eklemenin zamanı geldi.

  1. XAML penceresinde Window> öğesine tıklayarak <ana pencereyi seçin.

  2. Özellikler penceresinde sağ üstteki Olaylar'ı seçin, ardından Yüklenen etiketinin sağındaki metin kutusuna çift tıklayın.

    Main Window Properties

Bu sizi formun arkasındaki koda getirir; şimdi veri erişimi gerçekleştirmek için kullanmak ProductContext üzere kodu düzenleyeceğiz. Kodu aşağıda gösterildiği gibi güncelleştirin.

Kod, uzun süre çalışan bir örneğini ProductContextbildirir. ProductContext nesnesi, verileri sorgulamak ve veritabanına kaydetmek için kullanılır. Ardından Dispose() örnekteki ProductContext yöntemi geçersiz kılınan yöntemden çağrılır OnClosing . Kod açıklamaları her adımın ne yaptığını açıklar.

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);
        }
    }
}

Dekont

Kod, veritabanını ilk çalıştırmada derlemek için EnsureCreated() bir çağrı kullanır. Bu tanıtımlar için kabul edilebilir, ancak üretim uygulamalarında şemanızı yönetmek için geçişlere bakmanız gerekir. Kod ayrıca yerel bir SQLite veritabanı kullandığından zaman uyumlu olarak yürütülür. Genellikle uzak sunucu içeren üretim senaryoları için ve SaveChanges yöntemlerinin zaman uyumsuz sürümlerini Load kullanmayı göz önünde bulundurun.

WPF Uygulamasını Test Edin

F5 tuşuna basarak veya Hata Ayıklama Hata Ayıklamayı > Başlat'ı seçerek uygulamayı derleyin ve çalıştırın. Veritabanı adlı products.dbbir dosyayla otomatik olarak oluşturulmalıdır. Bir kategori adı girin ve Enter tuşuna basın, ardından alt kılavuza ürün ekleyin. Kaydet'e tıklayın ve veritabanı tarafından sağlanan kimliklerle kılavuz yenilemesini izleyin. Satırı vurgulayın ve satırı kaldırmak için Sil'e basın. Kaydet'e tıkladığınızda varlık silinir.

Running application

Özellik Değiştirme Bildirimi

Bu örnek, varlıkları kullanıcı arabirimiyle eşitlemek için dört adıma dayanır.

  1. İlk çağrı _context.Categories.Load() , kategori verilerini yükler.
  2. Yavaş yüklenen proxy'ler bağımlı ürün verilerini yükler.
  3. EF Core'un yerleşik değişiklik izlemesi, çağrıldığında _context.SaveChanges() eklemeler ve silmeler dahil olmak üzere varlıklarda gerekli değişiklikleri yapar.
  4. Yeni oluşturulan kimliklerle yeniden yüklemeyi zorlamak için DataGridView.Items.Refresh() çağrılar.

Bu, başlangıç örneğimizde işe yarar, ancak diğer senaryolar için ek kod gerektirebilirsiniz. WPF denetimleri, varlıklarınızdaki alanları ve özellikleri okuyarak kullanıcı arabirimini işler. Kullanıcı arabiriminde (UI) bir değeri düzenlediğinizde, bu değer varlığınıza geçirilir. Bir özelliğin değerini doğrudan varlığınızda değiştirdiğinizde (örneğin, veritabanından yüklerken), WPF kullanıcı arabirimindeki değişiklikleri hemen yansıtmaz. İşleme altyapısına değişiklikler bildirilmelidir. Proje bunu el ile çağırarak Refresh()yaptı. Bu bildirimi otomatikleştirmenin kolay bir yolu, INotifyPropertyChanged arabirimini uygulamaktır. WPF bileşenleri arabirimi otomatik olarak algılar ve değişiklik olaylarına kaydolacaktır. Varlık bu olayları oluşturmakla sorumludur.

Bahşiş

Değişiklikleri işleme hakkında daha fazla bilgi edinmek için bkz. Özellik değişikliği bildirimini uygulama.

Sonraki Adımlar

DbContext Yapılandırma hakkında daha fazla bilgi edinin.