Veri bağlamaya giriş
Bu derste, geçerli saati gösteren bir uygulama oluşturmayı öğreneceksiniz. Bu derste veri bağlama, koddan uygulamanızın kullanıcı arabirimine veri alma ve kullanıcı arabirimindeki saat görünümünü güncelleştirmek için verileri yenileme ile ilgili temel bilgiler yer alır. Bu ders, sonraki derslerde daha karmaşık veri bağlama görevlerinin temelini oluşturur. Hazırsanız başlayalım!
1. Projeyi oluşturma
Henüz çalışmıyorsa Visual Studio'yu açın. Boş Uygulama (Evrensel Windows) şablonunu kullanarak yeni bir C# Windows Evrensel projesi oluşturun. Buna DatabindingSample adını ver. Bu proje, kullanıcı arabirimi ve Veri modülünün tamamında birlikte çalışacağınız projedir.
Tamam'a tıkladığınızda Visual Studio, hedef ve en düşük Windows sürümlerini girmenizi ister. Bu proje yalnızca bir alıştırma projesidir ve bunu windows'un eski bir sürümünü çalıştıran bilgisayarlara dağıtmayı planlamıyorsunuz. Bu nedenle, hem en düşük hem de hedef sürüm için Windows'un en son sürümünü seçip Tamam'a tıklayabilirsiniz.
2. Saat ekranı için TextBlock ekleyin
Proje tam olarak başlatılıp yüklendiğinde, Çözüm Gezgini çift tıklayarak açınMainPage.xaml
.
Bahşiş
Ekran alanınız azaldıysa, düzenleyiciyi daha düşük çözünürlüklü bir ekranın benzetimini yapmak üzere değiştirmek için sol üst köşedeki açılan listeyi kullanın. Bu modül için %13,3 Masaüstü (1280x720) %100 ölçek kullanmanızı öneririz, ancak en rahatı en rahat hissedeni seçin.
Öğesinin açma ve kapatma etiketleri Grid
arasına aşağıdaki satırı ekleyin.
<TextBlock HorizontalAlignment="Right"
Margin="10"
Text="{x:Bind CurrentTime}" />
Bu, pencerenin sağ üst tarafında kenardan 10 birimlik bir kenar boşluğu ile yeni TextBlock
bir oluşturur. Şimdi öğesinin Text
TextBlock
adresini verelim.
Bölümü Text={x:Bind CurrentTime}
, veri bağlama ile ilk karşılaşmanızdır. x:Bind
, uygulamanızın geri kalanıyla birlikte C# kodunda derlenmiş bir XAML işaretleme uzantısıdır. Burada özelliğini özelliğine TextBlock
CurrentTime
bağlarText
. Projeyi şimdi derlemeye çalışırsanız aşağıdaki hata iletisini alırsınız:
XamlCompiler hata WMC1110: Geçersiz bağlama yolu 'CurrentTime' : 'CurrentTime' özelliği 'MainPage' türünde bulunamadı
Bu, derleyicinin içinde MainPage
bir CurrentTime
özelliği eksik olduğunu gösterir. Bu özelliği oluşturduktan sonra içeriği sağ üst köşede görüntülenir TextBlock
.
Dekont
UWP, şuna benzer eski bir veri bağlama yöntemini de destekler: Text={Bind CurrentTime}
. Bu eski yöntem, değerinden {x:Bind}
biraz farklı çalışır. En önemlisi, yazım hatası varsa derleme süresi hataları sunmaz. Bu modülde yalnızca derleme zamanı hata denetimi sağlayan yeni {x:Bind}
bağlama yöntemine odaklanacağız. Ancak, {x:Bind}
sürümünden daha {Bind}
olgun değildir ve yeni özellikler alır. Bu nedenle projeyi oluşturmak için en son Windows sürümünü seçtik.
3. Özelliği oluşturma CurrentTime
MainPage.xaml.cs dosyasını açın ve sınıfına MainPage
aşağıdaki özellik tanımını ekleyin.
public string CurrentTime => DateTime.Now.ToLongTimeString();
Yukarıdaki söz dizimini bilmiyorsanız, buna ifade gövdeli üye adı verilir. C# 6.0'da kullanıma sunulmuştur ve aşağıdakiler için kısaltmadır:
public string CurrentTime
{
get { return DateTime.Now.ToLongTimeString(); }
}
4. Uygulamayı çalıştırma
Uygulamayı şimdi başlatırsanız (menüde F5 tuşunu veya Hata Ayıklama / Hata Ayıklamayı Başlat komutunu kullanarak), uygulama derlenip çalışır. Daha da iyisi işe yaramış gibi görünmesidir! Geçerli saat sağ üst köşede görüntülenir.
Ancak saat güncel olmadığından bir sorun var. Uygulama ilk kez başlatıldığında takılı kalır. uygulama içindeki değeri TextBlock
ne zaman yenileyeceğini nasıl bilir? UWP çalışma zamanına saniyede bir kez güncelleştirmesini söylemeliyiz.
5. Bağlama modlarını belirtin
{x:Bind}
bağlamaları performans için son derece iyileştirilmiştir. Bu, geliştiricinin açıkça istemediği bir şey yapmadığı anlamına gelir. Bu nedenle varsayılan olarak bağlama, {x:Bind}
bağlama kaynağını (bizim durumumuzda CurrentTime
özellik) yalnızca bir kez değerlendirir. Bu bağlama türü bağlama olarak adlandırılır OneTime
. UWP çerçevesinin kullanıcı arabirimini güncelleştirmeyi sürdürmesini istiyorsak, açıkça başka bir bağlama modu belirtmemiz gerekir: OneWay
veya TwoWay
.
TwoWay
bağlama modu, C# kodumuz (mantık) ile kullanıcı arabirimi arasında çift yönlü bir bağlama olduğunu gösterir. Bu bağlama türü daha sonra kullanıcının işleyebileceği denetimlere bağlandığımızda yararlı olacaktır. Ancak bir TextBlock
için OneWay
bağlama tercih edilir çünkü veri değişiklikleri yalnızca koddan kaynaklanır, hiçbir zaman kullanıcı arabiriminde kaynaklanır.
bizim için bir OneWay
bağlama modu belirtmek için olarak değiştirin {x:Bind CurrentTime}
{x:Bind CurrentTime, Mode=OneWay}
.TextBlock
içindeki etiketin Grid
tamamı TextBlock
artık bu işaretleme gibi görünmelidir.
<TextBlock HorizontalAlignment="Right"
Margin="10"
Text="{x:Bind CurrentTime, Mode=OneWay}" />
Bağlama, UWP çalışma zamanına özelliğindeki değişiklikleri izlemek için gerekli altyapıyı oluşturmasını CurrentTime
ve bunu Text
öğesine yansıtmasını bildirir TextBlock
. Bu ek altyapı çok az miktarda bellek ve CPU döngüsü kaplar ve bu nedenle varsayılan değildir.
Uygulamayı şimdi çalıştırırsanız saat yine de güncelleştirilmiyor. Özelliğin CurrentTime
değiştiğini sisteme bildirmemiz gerekir.
6. Arabirimi uygulama INotifyPropertyChanged
Bu bildirim arabirim aracılığıyla INotifyPropertyChanged
gerçekleşir. Tek bir olayı olan basit bir arabirimdir.
public interface INotifyPropertyChanged
{
event PropertyChangedEventHandler PropertyChanged;
}
Veri bağlama kaynağı olarak basit bir C# özelliğine sahip olan tüm sınıflar arabirimini INotifyPropertyChanged
uygulamalıdır. Kullanıcı arabirimi güncelleştirilmesi gerektiğinde sınıfın PropertyChanged
olayı tetiklemesi gerekir. Şimdi sınıf bildirimine arabirimini MainPage
ekleyelim.
public sealed partial class MainPage : Page, INotifyPropertyChanged
Ayrıca sınıfına olayı ekleyerek PropertyChanged
arabirimini uygulamamız gerekir.
public event PropertyChangedEventHandler PropertyChanged;
7. Olayı her saniye çağırın PropertyChanged
Geriye kalan tek şey, saati her güncelleştirmek istediğimizde (yani her saniye) olayı çağırmaktır PropertyChanged
. Başlamak için sınıfında bir DispatcherTimer
nesne MainPage
bildirelim.
private DispatcherTimer _timer;
Şimdi oluşturucuda (çağrıdan InitializeComponent
sonra) her saniye tetiklemesi için ayarlayalım.
_timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1) };
_timer.Tick += (sender, o) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(CurrentTime)));
_timer.Start();
Yukarıdaki ilk satır zamanlayıcıyı bir saniyelik aralıkla oluşturur ve son satır bunu başlatır. Zamanlayıcı tetiklendiğinde ne olduğunu inceleyelim (ikinci satırda).
PropertyChanged?.Invoke
, bir olayın null olup olmadığını denetlemek ve değilse çağırmak için kısaltmadır. Çoğu olay gibi, ilk bağımsız değişken gönderendir (this
). Olayın ikinci bağımsız değişkeni PropertyChanged
, özellik adı olarak dize bekleyen bir oluşturucuya sahip olan yeni oluşturulan PropertyChangedEventArgs
bir nesnedir. Bu nedenle olayın aboneleri PropertyChanged
(bu durumda UWP sistemi) güncelleştirilmiş özelliğin adını alır ve buna göre hareket edebilir.
Bahşiş
Özellik adı için dize değişmez değerlerini (örneğin "CurrentTime"
) kullanmayın. Dizenin kendisini kullanmak yazım hatasına açıktır ve bu da kullanıcı arabirimi güncelleştirilmediğinde hata ayıklaması zor sorunlara neden olabilir. Ayrıca, dize sabitleri güncelleştirilmezse özelliğin masum bir şekilde yeniden adlandırılması da hatalara neden olabilir. Yazım hatasına karşı bağışık olan ve yeniden adlandırmaları izleyebilen ifadeyi nameof
her zaman kullanmak iyi bir uygulamadır.
MainPage.xaml.cs dosyasının tamamı aşağıdaki gibi görünmelidir:
namespace DatabindingSample
{
public sealed partial class MainPage : Page, INotifyPropertyChanged
{
private DispatcherTimer _timer;
public MainPage()
{
this.InitializeComponent();
_timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1) };
_timer.Tick += (sender, o) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(CurrentTime)));
_timer.Start();
}
public string CurrentTime => DateTime.Now.ToLongTimeString();
public event PropertyChangedEventHandler PropertyChanged;
}
}
8. Uygulamayı çalıştırma
Uygulamayı şimdi çalıştırırsanız saat güncelleştirilir. Tebrikler, ilk veri bağlamanızı oluşturdunuz!
9. Özet
Artık koddan UWP uygulamanızın kullanıcı arabirimine veri almanın hızlı ve otomatik bir yolunu oluşturmak için } kullanmayı {x:Bind
biliyorsunuz. Bu teknik derleme sırasında denetleniyor. Ayrıca arabirimini de tanımaya INotifyPropertyChanged
başladınız. Bu arabirim, bir veri bağlama özelliği değiştiğinde ve kullanıcı arabiriminin güncelleştirilmesi gerektiğinde uygulamanızın UWP çerçevesine bildirmesine olanak tanır.
1. Projeyi oluşturma
Henüz çalışmıyorsa Visual Studio'yu açın. WPF Uygulaması şablonunu kullanarak yeni bir C# WPF projesi oluşturun. Bunu DatabindingSampleWPF olarak adlandırıp Tamam'ı seçin. Bu proje, kullanıcı arabirimi ve Veri modülünün tamamında birlikte çalışacağınız projedir.
2. Clock sınıfını oluşturma
Görevimiz geçerli saati görüntülemek olduğundan, önce bir Clock
sınıf oluşturmak mantıklıdır. Çözüm Gezgini'de projeye sağ tıklayınDatabindingSampleWPF
, Ekle / Sınıf'ı seçin ve sınıfın adı olarak girinClock
.
Aşağıdaki kodu yeni oluşturulan dosyaya kopyalayın:
using System;
namespace DatabindingSampleWPF
{
public class Clock
{
public string CurrentTime => DateTime.Now.ToLongTimeString();
}
}
Özelliğin yukarıdaki söz dizimini CurrentTime
bilmiyorsanız, buna ifade gövdeli üye adı verilir. C# 6.0'da kullanıma sunulmuştur ve aşağıdakiler için kısaltmadır:
public string CurrentTime
{
get { return DateTime.Now.ToLongTimeString(); }
}
Gördüğünüz gibi, sınıfın şu ana kadar sahip Clock
olduğu tüm özellikler, geçerli saati uzun bir zaman biçiminde döndüren basit string
bir özelliktir. Sonraki adım, uygulamanın kendi içinde saati görüntülemektir.
3. Saat ekranı için TextBlock ekleyin
Visual Studio'da açtıysanız MainWindow.xaml
sekmesini seçin. Aksi takdirde, Çözüm Gezgini çift tıklayarak açabilirsiniz.
Öğesinin açma ve kapatma etiketleri Grid
arasına aşağıdaki satırı ekleyin.
<TextBlock HorizontalAlignment="Right"
VerticalAlignment="Top"
Margin="10"
Text="{Binding CurrentTime}">
<TextBlock.DataContext>
<local:Clock/>
</TextBlock.DataContext>
</TextBlock>
Bu işaretleme, pencerenin sağ üst tarafında, kenardan 10 birimlik kenar boşluğuyla yeni TextBlock
bir oluşturur.
Bölümü Text="{Binding CurrentTime}"
, veri bağlama ile ilk karşılaşmanızdır. {Binding}
bir XAML işaretleme uzantısıdır. Burada, özelliğini özelliğine TextBlock
CurrentTime
bağlar Text
- ancak CurrentTime
hangi nesnenin özelliği?
Veri bağlamanın başvurduğu nesne, içinde DataContext
TextBlock
örneği oluşturulur. Bu nedenle, yukarıdaki XAML kodu yalnızca bir TextBlock
denetim oluşturmakla kalmaz, aynı zamanda bir Clock
nesne örneği oluşturur. Ayrıca kod, öğesinin Text
TextBlock
CurrentTime
özelliğini, oluşturduğu nesnenin özelliğine Clock
bağlar. CurrentTime
Özelliği bağlamanın kaynağı olarak adlandırılırken Text
özelliği bağlamanın hedefi olarak adlandırılır.
4. Uygulamayı çalıştırma
Uygulamayı şimdi başlatırsanız (menüde F5 tuşunu veya Hata Ayıklama / Hata Ayıklamayı Başlat komutunu kullanarak), uygulama derlenip çalışır. Daha da iyisi işe yaramış gibi görünmesidir! Geçerli saat sağ üst köşede görüntülenir.
Ancak saat güncel olmadığından bir sorun var. Uygulama ilk kez başlatıldığında takılı kalır. uygulama içindeki değeri TextBlock
ne zaman yenileyeceğini nasıl bilir? WPF çalışma zamanına saniyede bir kez güncelleştirmesini söylemeliyiz.
Başka bir deyişle, özelliğin değiştiğini sisteme CurrentTime
bildirmemiz gerekir.
5. Arabirimi uygulama INotifyPropertyChanged
Bu bildirim arabirim aracılığıyla INotifyPropertyChanged
gerçekleşir. Tek bir olayı olan basit bir arabirimdir.
public interface INotifyPropertyChanged
{
event PropertyChangedEventHandler PropertyChanged;
}
Veri bağlama kaynağı olarak basit bir C# özelliğine sahip olan tüm sınıflar arabirimini INotifyPropertyChanged
uygulamalıdır. Kullanıcı arabirimi güncelleştirilmesi gerektiğinde sınıfın PropertyChanged
olayı tetiklemesi gerekir. Şimdi sınıf bildirimine arabirimini Clock
ekleyelim.
using System.ComponentModel;
public class Clock : INotifyPropertyChanged
{
Ayrıca sınıfına olayı ekleyerek PropertyChanged
arabirimini uygulamamız gerekir.
public event PropertyChangedEventHandler? PropertyChanged;
6. Olayı her saniye çağırın PropertyChanged
Geriye kalan tek şey, saati her güncelleştirmek istediğimizde (yani her saniye) olayı çağırmaktır PropertyChanged
. Başlamak için ad alanını System.Windows.Threading
s öğesine using
ekleyelim ve sınıfında bir DispatcherTimer
nesne Clock
bildirelim.
private DispatcherTimer _timer;
Şimdi oluşturucuda her saniye tetiklemesi için ayarlayın.
public Clock()
{
_timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1) };
_timer.Tick += (sender, o) => PropertyChanged?.Invoke(this,
new PropertyChangedEventArgs(nameof(CurrentTime)));
_timer.Start();
}
Oluşturucudaki ilk satır zamanlayıcıyı bir saniyelik aralıkla oluşturur ve son satır bunu başlatır. Zamanlayıcı tetiklendiğinde ne olduğunu inceleyelim (ikinci satırda).
PropertyChanged?.Invoke
, bir olayın null olup olmadığını denetlemek ve değilse çağırmak için kısaltmadır. Çoğu olay gibi, ilk bağımsız değişken gönderendir (this
). Olayın ikinci bağımsız değişkeni PropertyChanged
, özellik adı olarak dize bekleyen bir oluşturucuya sahip olan yeni oluşturulan PropertyChangedEventArgs
bir nesnedir. Bu nedenle olayın aboneleri PropertyChanged
(bu örnekte WPF sistemi) güncelleştirilmiş özelliğin adını alır ve uygun şekilde hareket edebilir.
Bahşiş
Özellik adı için dize değişmez değerlerini (örneğin "CurrentTime"
) kullanmayın. Dizenin kendisini kullanmak yazım hatasına açıktır ve bu da kullanıcı arabirimi güncelleştirilmediğinde hata ayıklaması zor sorunlara neden olabilir. Ayrıca, dize sabitleri güncelleştirilmezse özelliğin masum bir şekilde yeniden adlandırılması da hatalara neden olabilir. Yazım hatasına karşı bağışık olan ve yeniden adlandırma işlemlerini izleyebilen ifadeyi nameof
her zaman kullanmak iyi bir uygulamadır.
Tüm Clock.cs
aşağıdaki gibi görünmelidir:
namespace DatabindingSampleWPF
{
using System;
using System.ComponentModel;
using System.Windows.Threading;
public class Clock : INotifyPropertyChanged
{
private DispatcherTimer _timer;
public string CurrentTime => DateTime.Now.ToLongTimeString();
public event PropertyChangedEventHandler PropertyChanged;
public Clock()
{
// setup _timer to refresh CurrentTime
_timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1) };
_timer.Tick += (sender, o) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(CurrentTime)));
_timer.Start();
}
}
}
7. Uygulamayı çalıştırma
Uygulamayı şimdi çalıştırırsanız saat güncelleştirilir. İlk veri bağlamanızı oluşturdunuz!
8. Özet
Artık koddan WPF uygulamanızın kullanıcı arabirimine veri almanın hızlı ve otomatik bir yolunu oluşturmak için nasıl kullanılacağını {Binding}
biliyorsunuz. Ayrıca arabirimini de tanımaya INotifyPropertyChanged
başladınız. Bu arabirim, bir veri bağlama özelliği değiştiğinde ve kullanıcı arabiriminin güncelleştirilmesi gerektiğinde uygulamanızın WPF çerçevesini bilgilendirmesine olanak tanır.