Veri bağlamaya giriş

Tamamlandı

Tech logo of U W P and W P F.

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!

Tech logo of U W P and W P F. W P F appears dimmed.

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.

Screenshot of the Visual Studio Create a new project dialog box.

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 TextTextBlockadresini 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 TextBlockCurrentTime 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 MainPagebir 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.

Screenshot of the running app with the clock.

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 TextBlockne 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 TextBlockiç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:Bindbiliyorsunuz. 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.

Tech logo of U W P and W P F. U W P appears dimmed.

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.

Screenshot of the Visual Studio Create a new WPF project dialog box.

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 TextBlockCurrentTime bağlar Text - ancak CurrentTime hangi nesnenin özelliği?

Veri bağlamanın başvurduğu nesne, içinde DataContextTextBlockö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 TextTextBlockCurrentTime ö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.

Screenshot of the running app with the clock.

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 TextBlockne 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 usingekleyelim 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.