This article has been localized into Swedish by the community.
Felsöka databindningar
Eftersom databindningar evalueras under körning utan att fel indikeras genom ”exceptions”, kan en felaktig bindning ibland vara mycket svår att upptäcka. Sådana problem kan uppstå i flera olika situationer, men ett vanligt fall är att du försöker binda till en egenskap som inte existerar, antingen för att du kommer ihåg namnet fel eller att du helt enkelt stavade namnet fel. Här är ett exempel:
<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>
Fönstret ”Output”
Först bör du titta i fönstret ”Output” i Visual Studio. Om det inte är synligt kan du aktivera det med knapptryckningen [Ctrl+Alt+O]. Där finns massor av resultat från felsökaren, men någonstans bör du kunna hitta en rad som denna när du kör exemplet ovan:
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')
Innehållet kan tyckas en aning svårgenomträngligt, främst eftersom det inte finns några radbrytningar i detta långa meddelande, men den viktiga delen är denna:
'NonExistingProperty' property not found on 'object' ''Grid' (Name='pnlMain')'.
Den talar om för dig att du har försökt använda en egenskap "NonExistingProperty" på ett objekt av typ ”Grid” med namnet ”pnlMain”. Denna koncisa information bör kunna hjälpa dig att rätta namnet egenskapen eller att binda den till ett verkligt objekt, om det detta som är problemet.
Justering av spårnivån
I exemplet ovan var problemet ganska enkelt att fixa till, eftersom WPF kunde identifiera vad vi försökte göra och kunde indikera varför det inte fungerade. Men studera nästa exempel:
<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>
Här försöker vi binda egenskapen ”Title”, men till vilket objekt? Som vi såg i avsnittet om ”DataContext” kommer WPF att använda egenskapen ”DataContext” på textblocket som kan vara nedärvt genom hierarkin, men i detta exempel har vi glömt att ange ett ”DataContext”. Detta innebär att vi försöker nå en egenskap för ett ”null”-objekt. WPF kommer att tolka detta som en helt legitim bindning för ett objekt som ännu inte har initierats, och därför har WPF ingen anledning att klaga. Om du kör detta exempel och studerar Output-fönstret kommer du inte att upptäcka några bindningsfel.
För de fall exikveringen inte ger förväntat resultat finns det ett sätt att tvinga WPF att redogöra för alla bindnigsproblem som dyker upp. Detta kan göras genom att ange ett värde på ”TraceLevel” på objektet ”PresentationTraceSources” som finns i ”Namespace” ”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>
Notera att vi har lagt till en referens till ”System.Diagnostics” i Window-taggen och sedan använt ”TraceLevel” i bindningen. WPF kommer nu att ge massor av information om denna bindning i Output-fönstret.
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 ''
Genom att läsa genom denna lista kan du se hela processen som WPF går igenom för att försöka hitta ett adekvat värde för ditt textblock. Många gånger kommer WPF att misslyckas med att hitta en adekvat ”DataContext” för att slutligen använda standarden {DependencyProperty.UnsetValue} vilket skall tolkas som en tom sträng.
Använda den riktiga felsökaren
Tricket ovan kan fungera bra för att diagnostisera en dålig bindning, men ibland är det lättare och trevligare att använda den riktiga felsökaren. Bindningar i sig stöder inte detta eftersom de hanteras djupt i det inre av WPF, men använder man en omvandlare som vi gjorde i föregående avsnitt, kan man gå igenom processen stegvis. Man behöver faktiskt inte en riktig omvandlare som utför riktiga uppgifter, det enda man behöver är ett sätt att komma in i bindningsprocessen, för detta ändamål duger det att använda en dummy-omvandlare:
<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;
}
}
}
I denbakomliggande koden definierar vi en ”DebugDummyConverter”. I metoderna ”Convert()” och ”ConvertBack()” anropar vi ”Debugger.Break()” som har samma effekt som en ”breakpoint” i Visual Studio, och som returnerar ingångsvärdet.
I XAML-koden lägger vi till en referens till vår omvandlare som resurs och sedan kan vi utnyttja omvandlaren i vår bindning. I en verklig tillämpning bör du definiera omvandlaren i en egen fil och sedan referera till denna i App.xaml så att du kan använda den överallt i applikationen utan behöva skapa nya referenser i varje fönster. För detta exempel duger dock koden ovan.
Om du kör exemplet kommer du att se att felsökaren stannar så snart WPF försöker hämta värdet på fönstrets titel. Du kan nu inspektera värden som ges till metoden ”Convert()” eller t. o. m. ändra dem innan exekveringen fortsätter med hjälp av felsökarens standard felsökningsmekanismer i Visual Studio.
Om felsökaren aldrig stannar betyder detta att omvandlaren aldrig anropas. Detta är vanligtvis en indikation på att du har ett ogiltigt bindningsuttryck, vilket kan diagnostiseras med hjälp av metoderna som beskrevs i början av avsnittet. Dummy-omvandlaren är endast till för att testa giltiga bindningsuttryck.