Per continuare il discorso sul debug del databinding di WPF, vediamo come ci può essere d’aiuto il namespace System.Diagnostic, presente nella dll WindowsBase. Per effettuare il databinding, infatti, è possibile utilizzare una attached property da impiegare sui seguenti oggetti:
- System.Windows.Data.BindingBase
- System.Windows.Data.BindingExpressionBase
- System.Windows.Data.ObjectDataProvider
- System.Windows.Data.XmlDataProvider
L’attached property in questione è la PresentationTraceSources.TraceLevel. Questa può essere impostata a diversi livelli, ovvero:
- None: nessun trace del databinding;
- Low: genera solo le informazioni essenziali per il binding, e le eccezioni che si possono presentare;
- Medium: viene generato un numero di informazioni piuttosto elevato qualora il binding vada in errore, mentre se il binding è corretto vengono minimizzate le informazioni;
- High: Massimo livello di informazioni. Viene loggato il valore, il valore sorgente, quello di destinazione, le eccezioni con massimo livello di dettaglio;
Come è possibile utilizzare questa tecnica di “instrumenting” della nostra applicazione? Di fatto è piuttosto semplice, in quanto è sufficiente includere il namespace System.Diagnostics ed impiegare correttamente la attached property nello XAML come è possibile vedere nel codice seguente:
1: <Window x:Class="DatabindingDebug.Views.MainView2"
2: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4: xmlns:c="clr-namespace:DatabindingDebug.Commands"
5: xmlns:diagnostics="clr-namespace:System.Diagnostics;assembly=WindowsBase"
6: Title="Main Window" Height="400" Width="400">
7:
8: <Grid>
9: <Grid.RowDefinitions>
10: <RowDefinition Height="40" />
11: <RowDefinition Height="40" />
12: <RowDefinition Height="40" />
13: <RowDefinition Height="40" />
14: </Grid.RowDefinitions>
15: <TextBox Grid.Row="0" Margin="4,4,4,4" Text="{Binding Path=Name, diagnostics:PresentationTraceSources.TraceLevel=High}"/>
16: <TextBox Grid.Row="1" Margin="4,4,4,4" Text="{Binding Path=LastName, diagnostics:PresentationTraceSources.TraceLevel=High}"/>
17: <Slider Grid.Row="2" Margin="4,4,4,4" x:Name="sldValue"/>
18: <TextBox Grid.Row="3" Margin="4,4,4,4" Text="{Binding ElementName=sldValue, Path=Value, diagnostics:PresentationTraceSources.TraceLevel=High}"/>
19: </Grid>
20: </Window>
Ciò che viene generato nella console di output assomiglierà a questo:
1: System.Windows.Data Warning: 104 : BindingExpression (hash=35287174): At level 0 - for MainViewModel.Name found accessor <null>
2: System.Windows.Data Error: 39 : BindingExpression path error: 'Name' property not found on 'object' ''MainViewModel'
3: (HashCode=30923613)'. BindingExpression:Path=Name; DataItem='MainViewModel' (HashCode=30923613); target element is 'TextBox' (Name='');
4: target property is 'Text' (type 'String')
5: System.Windows.Data Warning: 76 : BindingExpression (hash=35287174): TransferValue - got raw value {DependencyProperty.UnsetValue}
6: System.Windows.Data Warning: 84 : BindingExpression (hash=35287174): TransferValue - using fallback/default value ''
7: System.Windows.Data Warning: 85 : BindingExpression (hash=35287174): TransferValue - using final value ''
8: System.Windows.Data Warning: 63 : BindingExpression (hash=42659827): Resolving source
9: System.Windows.Data Warning: 66 : BindingExpression (hash=42659827): Found data context element: TextBox (hash=40644060) (OK)
10: System.Windows.Data Warning: 74 : BindingExpression (hash=42659827): Activate with root item MainViewModel (hash=30923613)
11: System.Windows.Data Warning: 104 : BindingExpression (hash=42659827): At level 0 -
12: for MainViewModel.LastName found accessor RuntimePropertyInfo(LastName)
13: System.Windows.Data Warning: 100 : BindingExpression (hash=42659827): Replace item at level 0
14: with MainViewModel (hash=30923613), using accessor RuntimePropertyInfo(LastName)
15: System.Windows.Data Warning: 97 : BindingExpression (hash=42659827): GetValue at level 0 from
16: MainViewModel (hash=30923613) using RuntimePropertyInfo(LastName): 'Mario'
17: System.Windows.Data Warning: 76 : BindingExpression (hash=42659827): TransferValue - got raw value 'Mario'
18: System.Windows.Data Warning: 85 : BindingExpression (hash=42659827): TransferValue - using final value 'Mario'
Per cui come si può apprezzare, il livello di informazioni è piuttosto corposo.
Un’ultima considerazione: ricordate sempre di rimuovere l’ attached property PresentationTraceSources.TraceLevel dal software che deve andare in produzione, in quanto l’onere che si paga in termini di performance per la generazione della tracciatura del databinding è molto elevato. Da usare SOLO in fase di sviluppo, quindi!