This article has been localized into Ukrainian by the community.
Налагоджування прив'язки даних
Оскільки прив'язка даних здійснюється в час виконання, коли жодні виключення не викидаються при помилках, погану прив'язку інколи буває складно відстежити. Ці проблеми можуть виникнути в кількох ситуаціях, та найпоширенішою є та, що виникає при спробі прив'язати властивість, якої не існує, тобто введено неправильне ім'я. Ось приклад:
<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>
Вікно виводу
Преш за все ви захочете поглянути на вікно виводу Visual Studio. Зазвичай воно у нижній частині вікна програми. Також до нього можна перейти через комбінацію клавіш Ctrl + Alt + O. У вікні буде безліч даних від налагоджувача, серед яких ви знайдете щось на кшталт рядка нижче:
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')
Він може здатися трохи надмірним, оскільки це довжелезне повідомлення ніяк не розділене, однак важливим тут є наступне:
'NonExistingProperty' property not found on 'object' ''Grid' (Name='pnlMain')'.
Воно повідомляє про те, що ви намагались викликати властивість під назвою "NonExistingProprty" на об'єкті типу Grid названого "pnlName". Стало спокійніше, тепер зрозуміло, що слід відредагувати ім'я властивості чи здійснити прив'язку до реального об'єкта, якщо проблема в цьому.
Коригування рівня відстеження
Приклад вище було легко полагодити, оскільки WPF чітко розумів, що ми хтіли зробити й чому це не спрацювало. Розгляньмо наступний приклад:
<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>
Я намагаюся прив'язатись до властивості "Title", але якого об'єкту? Як сказано в статті про data cotexts, WPF використає властивість DaraContext TetxBlock'y, яка успадковується вниз по ієрархії елементів інтерфейсу. Та в цьому прикладі я забув означити data context. Виходить, що я хочу отримати властивість NULL-об'єкта. WPF gather. Якщо ви запустите цей приклад і глянете у вікно виводу, то не побачите жодних помилок прив'язки.
Однак, для випадків, коли ви не очікуєте такої поведінки, існує спосіб змусити WPF повідомити вам про всі проблеми зв'язування, з якими він стикається. Це можна зробити, встановивши значення TraceLevel на об'єкті PresentationTraceSources, який знаходиться у просторі імен 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>
Зверніть увагу, що я додав посилання на простір імен System.Diagnostics у верхній частині, а потім використав властивість на прив'язці. Тепер WPF надасть вам багато інформації про цю конкретну прив'язку у вікні 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 ''
Прочитавши цей список, ви зможете побачити весь процес, який проходить WPF, намагаючись знайти правильне значення для вашого елемента управління TextBlock. Кілька разів ви побачите, що він не може знайти відповідний DataContext, і врешті-решт, він використовує значення за замовчуванням {DependencyProperty.UnsetValue}, яке перетворюється на порожній рядок.
Використання реального налагоджувача
Описаний вище трюк може бути чудовим для діагностики поганого зв'язування, але в деяких випадках простіше і приємніше працювати зі справжнім відладчиком. Прив'язки не підтримують таку можливість, оскільки вони обробляються глибоко всередині WPF, але за допомогою конвертера, як показано в попередній статті, ви можете фактично зануритися в цей процес і пройти його. Вам не потрібен конвертер, який робить щось корисне, вам просто потрібен шлях до процесу зв'язування, і фіктивний конвертер допоможе вам у цьому:
<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;
}
}
}
У файлі Code-behind визначаємо DebugDummyConverter. У методах Convert() і ConvertBack() ми викликаємо Debugger.Break(), що має той самий ефект, що і встановлення точки зупинки у Visual Studio, а потім повертаємо недоторканим отримане значення.
У розмітці ми додаємо посилання на наш конвертер у ресурси вікна, а потім використовуємо його у прив'язці. У реальному додатку ви повинні визначити конвертер у власному файлі, а потім додати посилання на нього в App.xaml, щоб ви могли використовувати його в усьому додатку без необхідності створювати нове посилання на нього в кожному вікні, але для цього прикладу вищеописаний спосіб підійде чудово.
Якщо ви запустите приклад, то побачите, що відладчик переривається, як тільки WPF намагається отримати значення заголовка вікна. Тепер ви можете перевірити значення передані методу Convert(), або навіть змінити їх, перш ніж продовжити роботу, використовуючи стандартні можливості налагодження Visual Studio.
Якщо відладчик ніколи не переривається, це означає, що конвертер не використовується. Зазвичай це вказує на те, що у вас неправильний вираз зв'язування, який можна діагностувати і виправити за допомогою методів, описаних на початку цієї статті. Трюк з фіктивним конвертером призначений лише для перевірки коректних виразів зв'язування.