TOC

This article has been localized into Italian by the community.

Data binding:

Debugging data bindings

Siccome i binding dei dati sono valutati in fase di runtime, e non vengono sollevate eccezioni quando qualcosa va storto, un cattivo binding può essere molto difficile da rintracciare. Questi problemi possono verificarsi in diverse occasioni, ma l'errore più comune è quando si tenta si associare una proprietà che non esiste, perchè ti ricordi un nome sbagliato o perchè semplicemente abbiamo commesso un errore di battitura. Ecco qua un esempio:

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

La finestra di Output

Il primo posto dove vorrai guardare è la finestra di output di Visual Studio. Dovrebbe essere nella parte inferiore della finestra di Visual Studio, o è possibile attivarlo usando la scorciatoia [Ctrl + Alt + O]. Ci sarà un sacco di output dal debugger, ma da qualche parte dovresti trovare una linea come questa, quando esegui quanto sopra      esempio:

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

Questo potrebbe sembrare un po 'eccessivo, soprattutto perché in questo lungo messaggio non vengono utilizzate interruzioni di linea , ma la parte importante è questa:

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

Ti dice che hai provato ad usare una proprietà chiamata "NonExistingProperty" su un oggetto del tipo Grid, con il nome pnlMain. Questo è in realtà abbastanza conciso e dovrebbe aiutare a correggere il nome della proprietà o legarsi all'oggetto reale, se questo è il problema.

Regolazione del livello di tracciamento

L'esempio sopra è stato facile da correggere, perché era chiaro a WPF cosa stavamo cercando di fare e perché non funzionava. Considera però il successivo esempio:

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

Sto cercando di legare alla proprietà "Titolo", ma su quale oggetto? Come affermato nell'articolo sui contesti dei dati, WPF utilizzerà la proprietà DataContext sul TextBlock, che può essere ereditato lungo la gerarchia di controllo, ma in questo esempio, ho dimenticato di assegnare un contesto di dati. Questo in pratica significa che io sto cercando di ottenere una proprietà su un oggetto NULL. WPF capirà che questo potrebbe essere un binding perfettamente valido, ma che l'oggetto non è stato ancora inizializzato e quindi non si lamenterà di ciò. Se esegui questo esempio e guardi nella finestra Output , non vedrai errori di associazione.

Ci sono errori che non vengono però visualizzati nella finestra Output e che quindi non possono essere rintracciati in questo modo. C’è però un modo per costringere WPF a segnalare questi errori: si può impostare il TraceLevel sull’oggetto PresentationTraceSources, che si può trovare nel 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>

Si noti che ho aggiunto un riferimento allo spazio dei nomi System.Diagnostics nella parte superiore e quindi ho utilizzato la proprietà sull'associazione. WPF ti darà ora moltissime informazioni su questo legame specifico nella finestra 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 ''

Leggendo la lista, puoi effettivamente vedere l'intero processo che WPF attraversa per cercare di trovare un valore appropriato per il tuo controllo TextBlock. Molte volte vedrai che non è in grado di trovare un DataContext corretto e, alla fine, utilizza il {DependencyProperty.UnsetValue} predefinito che si traduce in una stringa vuota.

Utilizzare il vero debugger

Il trucco visto sopra può essere ottimo per diagnosticare una cattiva associazione, ma per alcuni casi, è più facile e più piacevole lavorare con il vero debugger. Il Binding non è supportato nativamente, dal momento che viene gestito in profondità all'interno di WPF, ma utilizzando un convertitore, come mostrato in un precedente articolo, puoi effettivamente saltare in questo processo e attraversarlo. Non hai davvero bisogno di un convertitore che faccia qualcosa di utile, hai solo bisogno di un metodo per accedere al processo di associazione ed  un convertitore fittizio ti porterà lì:

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

Nel file Code-behind, definiamo un DebugDummyConverter. Nei metodi Convert () e ConvertBack (), chiamiamo Debugger.Break (), che ha lo stesso effetto di impostare un punto di interruzione in Visual Studio, e quindi restituire il valore che ci è stato dato intatto.

Nel markup, aggiungiamo un riferimento al nostro convertitore nelle risorse della finestra e quindi lo usiamo nella nostra associazione. In un'applicazione del mondo reale, dovresti definire il convertitore in un file a sé stante e quindi aggiungere il riferimento ad esso in App.xaml, in modo da poterlo utilizzare su tutta l'applicazione senza dover creare un nuovo riferimento ad esso in ogni finestra, ma per questo esempio, quanto sopra dovrebbe andar bene.

Se si esegue l'esempio, si noterà che il debugger si interrompe non appena WPF tenta di recuperare il valore per il titolo della finestra. Ora puoi ispezionare il valori dati al metodo Convert (), o anche modificarli prima di procedere, utilizzando le funzionalità di debug standard di Visual Studio.

Se il debugger non si ferma mai, significa che il convertitore non viene utilizzato. Questo di solito indica che hai un'espressione vincolante, che può essere diagnosticata e risolta utilizzando i metodi descritti all'inizio di questo articolo. Il trucco del dummy-converter è utile solo per testare espressioni di binding valide


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!