TOC

This article has been localized into Turkish by the community.

Veri bağlama (data binding):

Veri Bağlamada Hata Ayıklama

Veri bağlamalar çalışma zamanında gerçekleştirildiği ve başarısız olduğunda bir istisnai durum oluşturulmadığı için bazen kötü bir veri bağlamayı takip etmek çok zor olabilir. Bu problemler bir çok farklı durumlarda oluşur, ama en ortak olan biri mevcut olmayan bir özelliğe veri bağlamaya kalktığınızda ortaya çıkar, mesela özellik adını yanlış yazdığınızda. İşte bir örnek :

<Window x:Class="WpfTutorialSamples.DataBinding.DataBindingDebuggingSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="DataBindingDebuggingSample" Height="100" Width="200">
    <Grid Margin="10" Name="pnlMain">
		<TextBlock Text="{Binding NonExistingProperty, ElementName=pnlMain}" />
	</Grid>
</Window>

Çıktı penceresi

İlk bakmak isteyeceğiniz yer Visual Studio programının Çıktı penceresi, ekranın alt kısmında bulunur, yoksa [Ctrl+Alt+O] tuşları ile aktif edebilirsiniz. Programı çalıştırdığınızda burada bir sürü mesaj göreceksiniz, fakat bir yerlerde şuna benzer bir mesaj çıkar :

System.Windows.Data Error: 40 : BindingExpression path error: 'NonExistingProperty' property not found on 'object' ''Grid' (Name='pnlMain')'. BindingExpression:Path=NonExistingProperty; DataItem='Grid' (Name='pnlMain'); target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')

Bu mesaj arada alatsatıra geçmeden devam ettiği için biraz bunaltıcı görünebilir, ama önemli olan parçası şurası :

'NonExistingProperty' property not found on 'object' ''Grid' (Name='pnlMain')'.

Diyor ki, adı pnlMain olan Grid tipinde bir nesneden "NonExistingProperty" adında bir özelliği kullanmaya kalktınız. Bu eğer hata buradaysa sizin isimdeki yazım hatasını düzeltmeniz veya gerçek bir nesneye bağlantı yapmanız için yeterli bir açıklama.

Hata takip seviyesini ayarlama

Yukarıdaki örnek düzenlenmesi kolaydı ve WPF için ne yapmaya çalıştığınızı anlamak ve neden çalışmadığını anlamak çok açıktı. Bir de şu örneği düşünün :

<Window x:Class="WpfTutorialSamples.DataBinding.DataBindingDebuggingSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="DataBindingDebuggingSample" Height="100" Width="200">
    <Grid Margin="10">
		<TextBlock Text="{Binding Title}" />
	</Grid>
</Window>

"Title" özelliğine veri bağlama yapmaya çalışıyorum, ama hangi nesnenin? Veri bağlamlarını incelerken WPF'nin bu durumda TextBlock kontrolünün DataContext özelliğinde yazılan değerden bunu algılayacağını gördük. Bu özellik kontrol hiyerarşisinde yukarıdan aşağıya geliyor, ancak ben burada DataContext özelliğine değer vermeyi unuttum. Bunun basitçe anlamı ben bir NULL nesneden bir özellik okumaya çalışıyorum. WPF bu durumda veri bağlamanın doğru yapıldığını ama kaynak nesneni henüz üretilmediğini farzedecek ve bir şikayet uyarısı vermeyecektir. Eğer bu örneği çalıştırır ve Çıktı penceresine bakarsanız, herhangi bir veri bağlama (binding) hatası görmezsiniz.

Bununla beraber beklediğiniz davranışın bu olmadığı durumlarda WPF'e içine düştüğü tüm veri bağlama sorunlarını bildirmesi için zorlama yapabilirsiniz. Bunu System.Diagnostics namespace içinde bulunan PresentationTraceSources nesnesinin TraceLevel özelliğini ayarlayarak yaparsınız :

<Window x:Class="WpfTutorialSamples.DataBinding.DataBindingDebuggingSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
        Title="DataBindingDebuggingSample" Height="100" Width="200">
    <Grid Margin="10">
		<TextBlock Text="{Binding Title, diag:PresentationTraceSources.TraceLevel=High}" />
	</Grid>
</Window>

Dikkat ederseniz önce yukarıda System.Diagnostics namespace'i dahil etmek için bir satır ekledim, ve sonra özelliği veri bağlamada kullandım. WPF artık belirtilen veri bağlama için Çıktı penceresinde size bir sürü bilgi verecektir :

System.Windows.Data Warning: 55 : Created BindingExpression (hash=2902278) for Binding (hash=52760599)
System.Windows.Data Warning: 57 :   Path: 'Title'
System.Windows.Data Warning: 59 : BindingExpression (hash=2902278): Default mode resolved to OneWay
System.Windows.Data Warning: 60 : BindingExpression (hash=2902278): Default update trigger resolved to PropertyChanged
System.Windows.Data Warning: 61 : BindingExpression (hash=2902278): Attach to System.Windows.Controls.TextBlock.Text (hash=18876224)
System.Windows.Data Warning: 66 : BindingExpression (hash=2902278): Resolving source
System.Windows.Data Warning: 69 : BindingExpression (hash=2902278): Found data context element: TextBlock (hash=18876224) (OK)
System.Windows.Data Warning: 70 : BindingExpression (hash=2902278): DataContext is null
System.Windows.Data Warning: 64 : BindingExpression (hash=2902278): Resolve source deferred
System.Windows.Data Warning: 66 : BindingExpression (hash=2902278): Resolving source
System.Windows.Data Warning: 69 : BindingExpression (hash=2902278): Found data context element: TextBlock (hash=18876224) (OK)
System.Windows.Data Warning: 70 : BindingExpression (hash=2902278): DataContext is null
System.Windows.Data Warning: 66 : BindingExpression (hash=2902278): Resolving source
System.Windows.Data Warning: 69 : BindingExpression (hash=2902278): Found data context element: TextBlock (hash=18876224) (OK)
System.Windows.Data Warning: 70 : BindingExpression (hash=2902278): DataContext is null
System.Windows.Data Warning: 66 : BindingExpression (hash=2902278): Resolving source
System.Windows.Data Warning: 69 : BindingExpression (hash=2902278): Found data context element: TextBlock (hash=18876224) (OK)
System.Windows.Data Warning: 70 : BindingExpression (hash=2902278): DataContext is null
System.Windows.Data Warning: 66 : BindingExpression (hash=2902278): Resolving source  (last chance)
System.Windows.Data Warning: 69 : BindingExpression (hash=2902278): Found data context element: TextBlock (hash=18876224) (OK)
System.Windows.Data Warning: 77 : BindingExpression (hash=2902278): Activate with root item <null>
System.Windows.Data Warning: 105 : BindingExpression (hash=2902278):   Item at level 0 is null - no accessor
System.Windows.Data Warning: 79 : BindingExpression (hash=2902278): TransferValue - got raw value {DependencyProperty.UnsetValue}
System.Windows.Data Warning: 87 : BindingExpression (hash=2902278): TransferValue - using fallback/default value ''
System.Windows.Data Warning: 88 : BindingExpression (hash=2902278): TransferValue - using final value ''

Listeyi okuyarak zavallı WPF'in TextBlock için bir değer bulmak amacıyla neler yaptığını tek tek görebilirsiniz. Farklı yerlerde sağlıklı bir DataContext bulunamadığına ait mesaj göreceksiniz, sonunda default {DependencyProperty.UnsetValue} özelliği değeri olan boş string değerini kabul ediyor.

Gerçek hata ayıklayıcıyı kullanmak

Yukarıda gösterilen ipuçları kötü bir veri bağlamayı incelemek için harika olabilir, fakat bazı durumlarda standart hata ayıklayıcı ile çalışmak daha kolay ve hoş olacaktır. Veri bağlamaların yapısında bu yok, çünkü onlar WPF'in derinliklerinde işleniyorlar, ama önceki örneklerde gösterilen gibi bir Dönüştürücü kullanarak prosesin içine dalıp adım adım gidebilirsiniz. Yazacağınız dönüştürücünün yararlı bir şey yapması gerekmiyor, size gereken veri bağlama işinin ortasında kesip bakmak, sahte bir dönüştürücü de sizi amaca ulaştırır :

<Window x:Class="WpfTutorialSamples.DataBinding.DataBindingDebuggingSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:self="clr-namespace:WpfTutorialSamples.DataBinding"
        Title="DataBindingDebuggingSample" Name="wnd" Height="100" Width="200">
	<Window.Resources>
		<self:DebugDummyConverter x:Key="DebugDummyConverter" />
	</Window.Resources>
    <Grid Margin="10">
		<TextBlock Text="{Binding Title, ElementName=wnd, Converter={StaticResource DebugDummyConverter}}" />
	</Grid>
</Window>
using System;
using System.Windows;
using System.Windows.Data;
using System.Diagnostics;

namespace WpfTutorialSamples.DataBinding
{
	public partial class DataBindingDebuggingSample : Window
	{
		public DataBindingDebuggingSample()
		{
			InitializeComponent();
		}
	}

	public class DebugDummyConverter : IValueConverter
	{
		public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
		{
			Debugger.Break();
			return value;
		}

		public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
		{
			Debugger.Break();
			return value;
		}
	}
}

Arkaplan kodunda DebugDummyConverter sınıfı tanımladık. Convert() ve ConvertBack() metodlarının her ikisinde de Debugger.Break() çağırarak Visual Studio'nun orada durmasını sağlıyoruz, sonra da gelen değeri hiç değiştirmeden geri veriyoruz.

Görsel kodunda Window.Resources içinde dönüştürücümüze referans veriyoruz ve sonra veri bağlamada kullanıyoruz. Bir gerçek dünya uygulamasında dönüştürücüyü kendisine ait bir dosya içine koymak ve referansını da App.xaml içinde vermek ve böylece her yerden erişmek mantıklıdır ama burada amacımız farklı olduğu için yukarıdaki gibi yapmak yeterli olacaktır.

Eğer örneği çalıştırırsanız, hata ayıklayıcının WPF pencere etiketi değerini okumaya kalktığında çalışmayı durdurduğunu göreceksiniz. Bu esnada çalışmaya ara verilen Convert() metodu içinde Visual Studio standart hata ayıklama kabiliyetlerini kullanarak isterseniz veri bağlaması yapılan değeri görebilir ve hatta değiştirebilirsiniz.

Eğer hata ayıklayıcının çalışmayı durdurmadığı bir sorunla karşılaşırsanız, bu dönüştürücünün hiç kullanılmadığı anlamına gelir ki, bu durumda veri bağlaması temelde yanlış yapılanmış demektir ve o sorunları yazının başında anlatılan tekniklerle çözersiniz. Sahte dönüştürücü işi sadece geçerli bir veri bağlama yaptığınız ama değerleri göremediğiniz durumlarda neler olduğunu takip etmek içindir.


This article has been fully translated into the following languages: Is your preferred language not on the list? Click here to help us translate this article into your language!