This article has been localized into Czech by the community.
Ladění datových vazeb (data bindings)
Protože datové vazby jsou vyhodnocovány za běhu a v případě selhání nejsou vyvolány žádné výjimky, může být špatně nastavená vazba někdy velmi těžko dohledatelná. Tyto problémy mohou nastat v několika různých situacích, ale běžným problémem je, když se pokoušíte vázat na vlastnost, která neexistuje, buď protože jste si špatně zapamatovali její název, nebo protože jste ji prostě špatně napsali. Zde je příklad:
<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>
Okno výstupu
Prvním místem, kam budete chtít nahlédnout, je okno Výstup ve Visual Studio. Mělo by být na spodní části vašeho okna Visual Studio, nebo ho můžete aktivovat pomocí klávesové zkratky [Ctrl+Alt+O]. Výstup ladicího programu bude obsahovat spoustu informací, ale někde byste měli najít řádek jako tento, když spustíte výše uvedený příklad:
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')
To může vypadat trochu přesyceně, hlavně proto, že v této dlouhé zprávě nejsou použity žádné odřádkování, ale důležitá část je tato:
'NonExistingProperty' property not found on 'object' ''Grid' (Name='pnlMain')'.
To vám říká, že jste se pokusili použít vlastnost s názvem "NonExistingProperty" na objektu typu Grid s názvem pnlMain. To je ve skutečnosti docela stručné a mělo by vám pomoci opravit název vlastnosti nebo se vázat na skutečný objekt, pokud to je problém.
Přizpůsobení úrovně trasování
Výše uvedený příklad bylo snadné opravit, protože pro WPF bylo jasné, co jsme se snažili udělat a proč to nefungovalo. Zvažte však tento další příklad:
<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>
Snažím se vázat na vlastnost "Title", ale na jakém objektu? Jak bylo uvedeno v článku o datových kontextech, WPF zde použije vlastnost DataContext na TextBlocku, která může být děděna dolů hierarchií ovládacích prvků, ale v tomto příkladě jsem zapomněl přiřadit datový kontext. To v podstatě znamená, že se snažím získat vlastnost na objektu NULL. WPF usoudí, že to může být zcela platná vazba, ale že objekt ještě nebyl inicializován, a proto se o tom nebude stěžovat. Pokud tento příklad spustíte a podíváte se do okna Output, neuvidíte žádné chyby vazby.
Nicméně, pro případy, kdy to není chování, které očekáváte, existuje způsob, jak donutit WPF, aby vám sdělilo o všech problémech s vazbami, do kterých narazí. Lze to provést nastavením TraceLevel na objektu PresentationTraceSources, který lze najít ve jmenném prostoru System.Diagnostics:
<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>
Všimněte si, že jsem na začátek přidal odkaz na jmenný prostor System.Diagnostics a poté použil vlastnost na vazbě. WPF vám nyní poskytne spoustu informací o této konkrétní vazbě v okně Output:
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 ''
Přečtením seznamu můžete vidět celý proces, kterým WPF prochází, aby se pokusilo najít vhodnou hodnotu pro váš ovládací prvek TextBlock. Několikrát uvidíte, že není schopen najít vhodný DataContext, a nakonec použije výchozí hodnotu {DependencyProperty.UnsetValue}, která se překládá do prázdného řetězce.
Použití skutečného debuggeru
Výše uvedený trik může být skvělý pro diagnostiku špatné vazby, ale v některých případech je snazší a příjemnější pracovat se skutečným debuggerem. Vazby toto nativně nepodporují, protože jsou zpracovávány hluboko uvnitř WPF, ale použitím převodníku, jak bylo ukázáno v předchozím článku, můžete ve skutečnosti vstoupit do tohoto procesu a postupně se jím proklikávat. Ve skutečnosti nepotřebujete převodník, který by dělal něco užitečného, jen potřebujete způsob, jak se dostat do procesu vazby, a falešný převodník vás tam dostane:
<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;
}
}
}
V souboru Code-behind definujeme DebugDummyConverter. V metodách Convert() a ConvertBack() voláme Debugger.Break(), což má stejný efekt jako nastavení breakpointu ve Visual Studio, a poté vrátíme hodnotu, která nám byla dána, nedotčenou.
V kódu značek přidáme odkaz na náš převodník do zdrojů okna a poté jej použijeme ve vazbě. V reálné aplikaci byste měli definovat převodník ve vlastním souboru a poté přidat na něj odkaz v App.xaml, abyste ho mohli používat po celé aplikaci bez nutnosti vytvářet nový odkaz na něj v každém okně, ale pro tento příklad by výše uvedené mělo stačit.
Pokud příklad spustíte, uvidíte, že debugger se přeruší, jakmile WPF se pokusí získat hodnotu pro titulek okna. Nyní můžete inspektovat hodnoty předané metodě Convert(), nebo je dokonce změnit před pokračováním, pomocí standardních ladících schopností Visual Studio.
Pokud se debugger nikdy nepřeruší, znamená to, že převodník není používán. To obvykle naznačuje, že máte neplatný výraz vazby, který lze diagnostikovat a opravit pomocí metod popsaných na začátku tohoto článku. Trik s falešným převodníkem je pouze pro testování platných výrazů vazby.