Как обнаружить сломанные привязки данных WPF?
При попытке ответить на вопрос в окрестности "Unit Testing WPF Bindings" У меня был следующий вопрос:
Какой лучший способ найти, если у вас неправильно настроена проводка привязки данных WPF (или вы просто сломали что-то, что было правильно подключено)?
Несмотря на то, что метод тестирования единицы измерения похож на то, что Джоэл "срывает руку", чтобы удалить осколок ". Я смотрю вокруг, чтобы сделать это легче. Накладные способы обнаружить это.
Кажется, что все привязаны к привязке данных с WPF.. и у него есть свои достоинства.
Ответы
Ответ 1
Лучшее, что я мог найти...
Так как каждый не может всегда следить за выходным окном в поисках ошибок привязки, мне понравился вариант №2. Что добавляет это в ваш App.Config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.diagnostics>
<sources>
<source name="System.Windows.Data" switchName="SourceSwitch" >
<listeners>
<add name="textListener" />
</listeners>
</source>
</sources>
<switches>
<add name="SourceSwitch" value="All" />
</switches>
<sharedListeners>
<add name="textListener"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="GraveOfBindErrors.txt" />
</sharedListeners>
<trace autoflush="true" indentsize="4"></trace>
</system.diagnostics>
</configuration>
Сопоставьте это с хорошим просмотром регулярных выражений script, чтобы извлечь соответствующую информацию, которую вы можете иногда запускать на GraveOfBindErrors.txt в выходной папке
System.Windows.Data Error: 35 : BindingExpression path error: 'MyProperty' property not found on 'object' ''MyWindow' (Name='')'. BindingExpression:Path=MyProperty; DataItem='MyWindow' (Name=''); target element is 'TextBox' (Name='txtValue2'); target property is 'Text' (type 'String')
Ответ 2
В .NET 3.5 был введен новый способ специально выводить информацию трассировки о конкретных привязках данных.
Это делается с помощью нового прикрепленного свойства System.Diagnostics.PresentationTraceSources.TraceLevel, которое вы можете применить к любому поставщику привязки или данных. Вот пример:
<Window x:Class="WpfApplication1.Window1"
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="Debug Binding Sample"
Height="300"
Width="300">
<StackPanel>
<TextBox Name="txtInput" />
<Label>
<Label.Content>
<Binding ElementName="txtInput"
Path="Text"
diag:PresentationTraceSources.TraceLevel="High" />
</Label.Content>
</Label>
</StackPanel>
</Window>
При этом будет отображаться информация о трассировке только для конкретной привязки в окне вывода Visual Studio без необходимости настройки трассировки.
Ответ 3
Вы можете использовать функцию отладки триггера WPF Inspector. Просто загрузите инструмент из codeplex и присоедините его к вашему запущенному приложению. Он также показывает ошибки привязки в нижней части окна.
Очень полезный инструмент!
![enter image description here]()
Ответ 4
Я использую представленное здесь решение, чтобы превратить ошибки привязки в собственные Исключения: http://www.jasonbock.net/jb/Default.aspx?blog=entry.0f221e047de740ee90722b248933a28d
Однако обычный сценарий в привязках WPF заключается в том, чтобы исключать исключения, если пользовательский ввод не может быть преобразован в целевой тип (например, TextBox привязан к целочисленному полю; ввод нечисловой строки приводит к FormatException, вход слишком большого числа приводит к исключению OverflowException). Аналогичный случай - когда Setter свойства source генерирует исключение.
Способ WPF для этого заключается через ValidatesOnExceptions = true и ValidationExceptionRule, чтобы сигнализировать пользователю, что введенный ввод неверен (с использованием сообщения об исключении).
Однако эти исключения также отправляются в окно вывода и, таким образом, "пойманы" BindingListener, что приводит к ошибке... явно не поведению, которое вы хотите.
Поэтому я расширил класс BindingListener
, чтобы НЕ выбрасывать исключение в следующих случаях:
private static readonly IList<string> m_MessagesToIgnore =
new List<String>()
{
//Windows.Data.Error 7
//Binding transfer from target to source failed because of an exception
//Normal WPF Scenario, requires ValidatesOnExceptions / ExceptionValidationRule
//To cope with these kind of errors
"ConvertBack cannot convert value",
//Windows.Data.Error 8
//Binding transfer from target to source failed because of an exception
//Normal WPF Scenario, requires ValidatesOnExceptions / ExceptionValidationRule
//To cope with these kind of errors
"Cannot save value from target back to source"
};
Измененные строки в public override void WriteLine (строковое сообщение):
....
if (this.InformationPropertyCount == 0)
{
//Only treat message as an exception if it is not to be ignored
if (!m_MessagesToIgnore.Any(
x => this.Message.StartsWith(x, StringComparison.InvariantCultureIgnoreCase)))
{
PresentationTraceSources.DataBindingSource.Listeners.Remove(this);
throw new BindingException(this.Message,
new BindingExceptionInformation(this.Callstack,
System.DateTime.Parse(this.DateTime),
this.LogicalOperationStack, int.Parse(this.ProcessId),
int.Parse(this.ThreadId), long.Parse(this.Timestamp)));
}
else
{
//Ignore message, reset values
this.IsFirstWrite = true;
this.DetermineInformationPropertyCount();
}
}
}
Ответ 5
Здесь полезен эффективный метод триггеров отладки/трассировки. Он позволяет регистрировать все действия триггера вместе с элементом, на который воздействуют:
http://www.wpfmentor.com/2009/01/how-to-debug-triggers-using-trigger.html
Ответ 6
Это было очень полезно для нас, но я хотел добавить к тем, кто считает это полезным, что есть утилита, которую Microsoft предоставляет с помощью sdk для чтения этого файла.
Найдено здесь: http://msdn.microsoft.com/en-us/library/ms732023.aspx
Чтобы открыть файл трассировки
1.Start Service Trace Viewer с помощью командной строки для перехода к вашему Место установки WCF (C:\Program Files\Microsoft SDK\Windows\v6.0\Bin), а затем введите SvcTraceViewer.exe. (хотя мы нашли наш в \v7.0\Bin)
Примечание. Средство просмотра службы трассировки может ассоциироваться с двумя типами файлов:.svclog и .stvproj. Вы можете использовать два параметры в командной строке для регистрации и отмените регистрацию расширений файлов.
/register: зарегистрировать ассоциацию расширения файлов ".svclog" и ".stvproj" с SvcTraceViewer.exe
/unregister: отмените регистрацию объединение расширений файлов ".svclog" и ".stvproj" с SvcTraceViewer.exe
1. Когда начнется просмотр службы трассировки, нажмите "Файл", а затем "Открыть". Перейдите в место, где файлы трассировки сохраняются.
2. Дважды щелкните файл трассировки, который вы хотите открыть.
Примечание. Нажмите SHIFT, несколько файлов трассировки для выбора и откройте их одновременно. обслуживание Trace Viewer объединяет содержимое всех файлов и представляет один вид. Для Например, вы можете открыть файлы трассировки как клиент, так и сервис. Это полезно, когда вы включили сообщение каротажа и распространения активности в конфигурации. Таким образом, вы можете изучить обмен сообщениями между клиента и сервиса. Вы также можете перетащить несколько файлов в программу просмотра или использовать вкладку "Проект". См. Управление Раздел проекта для более подробной информации.
3. Чтобы добавить дополнительные файлы трассировки в открытую коллекцию, нажмите "Файл" а затем укажите "Добавить". В окне который открывается, перейдите к местоположению файлов трассировки и дважды щелкните файл, который вы хотите добавить.
Кроме того, что касается фильтрации файла журнала, мы обнаружили, что эта ссылка чрезвычайно полезна:
http://msdn.microsoft.com/en-us/library/ms751526.aspx
Ответ 7
Для тех, кто любит меня, ищет чистый программный способ включения всех трассировок WPF на заданном уровне трассировки, вот часть кода, которая это делает. Для справки он основан на этой статье: Источники трассировки в WPF.
Это не требует изменения файла app.config, и он также не требует изменения реестра.
Вот как я его использую, в каком-то загрузочном месте (приложение и т.д.):
....
#if DEBUG
WpfUtilities.SetTracing();
#endif
....
И вот код утилиты (по умолчанию он отправляет все предупреждения в Слушатель трассировки по умолчанию):
public static void SetTracing()
{
SetTracing(SourceLevels.Warning, null);
}
public static void SetTracing(SourceLevels levels, TraceListener listener)
{
if (listener == null)
{
listener = new DefaultTraceListener();
}
// enable WPF tracing
PresentationTraceSources.Refresh();
// enable all WPF Trace sources (change this if you only want DataBindingSource)
foreach (PropertyInfo pi in typeof(PresentationTraceSources).GetProperties(BindingFlags.Static | BindingFlags.Public))
{
if (typeof(TraceSource).IsAssignableFrom(pi.PropertyType))
{
TraceSource ts = (TraceSource)pi.GetValue(null, null);
ts.Listeners.Add(listener);
ts.Switch.Level = levels;
}
}
}