TOC

This article has been localized into German by the community.

data binding:

Debuggen von Datenbindungen

Da Datenbindungen zur Laufzeit ausgewertet werden und keine Exceptions geworfen werden, wenn sie fehlschlagen, kann eine fehlerhafte Bindung manchmal sehr schwer aufzuspüren sein. Diese Probleme können in verschiedenen Situationen auftreten, aber ein häufiges Problem ist, wenn Sie versuchen, sich an eine Eigenschaft zu binden, die nicht existiert, entweder weil Sie sich an ihren Namen falsch erinnert haben oder weil Sie sie einfach falsch geschrieben haben. Hier ist ein Beispiel:

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

Das Ausgabe-Fenster

Der erste Ort, an dem Sie suchen sollten, ist das Visual Studio Output-Fenster. Es sollte sich am unteren Rand des Visual Studio-Fensters befinden, oder Sie können es mit der Tastenkombination [Strg+Alt+O] aktivieren. Sie werden viele Zeilen vom Debugger sehen, aber irgendwo sollte man eine Zeile wie diese finden, wenn man das obige Beispiel ausführt:

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')

Das erscheint zuerst einmal ziemlich verwirrend, weil all das in einer einzigen Zeile steht, aber der wichtige Teil davon ist dieser hier:

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

Er sagt Ihnen, dass Sie versucht haben, eine Eigenschaft namens "NonExistingProperty" auf einem Objekt vom Typ Grid mit dem Namen pnlMain zu verwenden. Das ist eigentlich ziemlich eindeutig und sollte Ihnen helfen, den Namen der Eigenschaft zu korrigieren oder an das reale Objekt zu binden, wenn das das Problem ist.

Einstellen des Trace Levels

Das obige Beispiel war einfach zu reparieren, weil es für WPF klar war, was wir versucht haben und warum es nicht funktionierte. Betrachten Sie dieses nächste Beispiel:

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

Ich versuche, mich an die Eigenschaft "Titel" zu binden, aber an welches Objekt? Wie im Artikel über Datenkontexte erwähnt, verwendet WPF hier die DataContext-Eigenschaft auf dem TextBlock, die in der Steuerungselemente-hierarchie vererbt werden kann, aber in diesem Beispiel habe ich vergessen, einen Datenkontext zuzuweisen. Dies bedeutet, dass ich versuche, eine Eigenschaft auf ein NULL-Objekt zu bekommen. WPF wird feststellen, dass es sich hierbei um eine vollkommen gültige Bindung handelt, aber dass das Objekt noch nicht initialisiert wurde und deshalb wird WPF sich darüber nicht beschweren. Wenn Sie dieses Beispiel ausführen und in das Output-Fenster schauen, sehen Sie keine Bindungsfehler.

Für die Fälle, wo das nicht das Verhalten ist, das Sie erwarten, gibt es eine Möglichkeit, WPF dazu zu zwingen, Ihnen die Bindungsprobleme zu berichten, auf die es stößt. Dies kann durch Setzen des TraceLevels im PresentationTraceSources-Objekt geschehen, das sich im Namensraum System.Diagnostics befindet:

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

Beachten Sie, dass ich einen Verweis auf den System.Diagnostics-Namensraum im oberen Bereich hinzugefügt habe und dann die Eigenschaft auf der Bindung verwendet habe. WPF zeigt Ihnen nun viele Informationen über diese spezielle Bindung im Output-Fenster:

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 ''

Indem Sie die Liste durchlesen, können Sie tatsächlich den gesamten Prozess sehen, den WPF durchläuft, um zu versuchen, einen richtigen Wert für Ihr TextBlock-Steuerelement zu finden. Mehrmals werden Sie sehen, dass es nicht in der Lage ist, einen richtigen DataContext zu finden, und am Ende verwendet es den Standard {DependencyProperty.UnsetValue}, der in einen leeren String übersetzt wird.

Verwenden des echten Debuggers

Der obige Trick kann nützlich sein, falsche Bindungs zu finden, aber in einigen Fällen ist es einfacher und angenehmer, mit dem wirklichen Debugger zu arbeiten. Bindungen unterstützen dies nicht nativ, da sie tief in WPF behandelt werden, aber mit einem Konverter, wie in einem früheren Artikel gezeigt, können Sie tatsächlich in diesen Prozess eingreifen und ihn durchlaufen. Sie brauchen nicht wirklich einen Konverter, der etwas Nützliches tut, Sie brauchen nur einen Weg in den Bindeprozess, und ein Dummy-Konverter wird Sie dorthin bringen:

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

In der Code-behind-Datei definieren wir einen DebugDummyConverter. In den Methoden Convert() und ConvertBack() rufen wir Debugger.Break() auf, was den gleichen Effekt hat wie das Setzen eines Breakpoints in Visual Studio, und geben dann den Wert zurück, der uns unverändert übergeben wurde.

Im Markup fügen wir einen Verweis auf unseren Konverter in den Window-Ressourcen hinzu und verwenden ihn dann in unserer Bindung. In einer realen Anwendung sollten Sie den Konverter in einer eigenen Datei definieren und dann den Verweis darauf in App.xaml hinzufügen, so dass Sie ihn überall in der Anwendung verwenden können, ohne in jedem Fenster einen neuen Verweis darauf erstellen zu müssen. Aber für dieses Beispiel ist es so gut genug.

Wenn Sie das Beispiel ausführen, werden Sie sehen, dass der Debugger abbricht, sobald WPF versucht, den Wert für den Titel des Fensters zu holen. Sie können nun die der Convert()-Methode gegebenen Werte überprüfen oder sogar ändern, bevor Sie fortfahren, indem Sie die Standard-Debugging-Funktionen von Visual Studio verwenden.

Wenn der Debugger nie abbricht, bedeutet dies, dass der Konverter nicht verwendet wird. Dies deutet in der Regel darauf hin, dass Sie einen ungültigen Bindungsausdruck haben, der mit den am Anfang dieses Artikels beschriebenen Methoden diagnostiziert und behoben werden kann. Der Dummy-Konverter-Trick dient nur zum Testen gültiger Bindungsausdrücke.


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!