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
- Visual Studio’yu açın
- Başlangıç penceresinde Yeni proje oluştur'u seçin.
- "WPF" araması yapın, WPF Uygulaması (.NET Core) öğesini ve ardından İleri'yi seçin.
- Sonraki ekranda projeye getStartedWPF gibi bir ad verin ve Oluştur'u seçin.
Entity Framework NuGet paketlerini yükleme
Çözüme sağ tıklayın ve Çözüm için NuGet Paketlerini Yönet... seçeneğini belirleyin .
Arama kutusuna yazın
entityframeworkcore.sqlite
.Microsoft.EntityFrameworkCore.Sqlite paketini seçin.
Sağ bölmede projeyi denetleyin ve Yükle'ye tıklayın
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
DbContext
yapı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.
Ana formu açmak için Çözüm Gezgini mainWindow.xaml öğesine çift tıklayın
XAML'yi düzenlemek için XAML sekmesini seçin.
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>
Bu, "üst" kategoriler için kaynak ve "ayrıntı" ürünleri için ikinci kaynak ayarlar.
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>
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_Click
bir 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:
Veri Etkileşimlerini İşleyen Kod Ekleme
Ana pencereye bazı olay işleyicileri eklemenin zamanı geldi.
XAML penceresinde Window> öğesine tıklayarak <ana pencereyi seçin.
Özellikler penceresinde sağ üstteki Olaylar'ı seçin, ardından Yüklenen etiketinin sağındaki metin kutusuna çift tıklayın.
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 ProductContext
bildirir. 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.db
bir 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.
Özellik Değiştirme Bildirimi
Bu örnek, varlıkları kullanıcı arabirimiyle eşitlemek için dört adıma dayanır.
- İlk çağrı
_context.Categories.Load()
, kategori verilerini yükler. - Yavaş yüklenen proxy'ler bağımlı ürün verilerini yükler.
- 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. - 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.