Как обнаружить нарушенную привязку данных WPF? - PullRequest
70 голосов
/ 03 декабря 2008

При попытке ответить на вопрос в окрестности ' Юнит-тестирование привязок WPF ' У меня возник следующий вопрос:
Какой лучший способ найти, если у вас неправильно настроена привязка WPF Data Binding (или вы просто сломали что-то правильно подключенное)?

Хотя подход модульного тестирования, похоже, похож на то, как Джоэл «отрывает руку, чтобы удалить занозу». Я ищу более простые и менее сложные способы обнаружения этого.

Кажется, что все взяли на себя обязательство в значительной степени связывать данные с WPF ... и у него есть свои преимущества.

Ответы [ 7 ]

68 голосов
/ 05 декабря 2008

В .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 без какой-либо настройки трассировки.

38 голосов
/ 03 декабря 2008

Лучшее, что я мог найти ...

Как отладить привязки WPF? Беатрис Штольниц

Поскольку все не всегда могут следить за окном вывода в поисках ошибок привязки, мне понравился вариант №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>

Сопоставьте это с хорошим сценарием регулярного выражения для извлечения соответствующей информации, которую вы можете иногда запускать в 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')
5 голосов
/ 28 декабря 2013

Вы можете использовать функцию отладки триггера в WPF Inspector. Просто скачайте инструмент из codeplex и прикрепите его к запущенному приложению. Это также показывает ошибки привязки внизу окна. Очень полезный инструмент!

enter image description here

4 голосов
/ 24 июля 2012

Я использую представленное здесь решение, чтобы превратить ошибки привязки в собственные исключения: http://www.jasonbock.net/jb/Default.aspx?blog=entry.0f221e047de740ee90722b248933a28d

Однако нормальный сценарий в привязках WPF - генерировать исключения в случае, если пользовательский ввод не может быть преобразован в целевой тип (например, TextBox, связанный с целочисленным полем; ввод нечисловой строки приводит к FormatException, ввод слишком большого числа приводит к OverflowException). Аналогичный случай, когда метод Setter исходного свойства генерирует исключение.

Способ обработки 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();
            }
        }
    }
2 голосов
/ 29 марта 2011

Это было очень полезно для нас, но я хотел добавить к тем, кто считает это полезным, что есть утилита, которую Microsoft предоставляет вместе с SDK для чтения этого файла.

Найдено здесь: http://msdn.microsoft.com/en-us/library/ms732023.aspx

Чтобы открыть файл трассировки

1. Запустите Service Trace Viewer, используя окно команд, чтобы перейти к Место установки WCF (C: \ Program Files \ Microsoft SDK \ Windows \ v6.0 \ Bin), а затем введите SvcTraceViewer.exe. (хотя мы нашли наш в \ v7.0 \ Bin)

Примечание. Средство просмотра служебной трассировки может ассоциироваться с двумя типами файлов: .svclog и .stvproj. Вы можете использовать два параметры в командной строке для регистрации и отмените регистрацию расширений файлов.

/ регистрация: зарегистрировать ассоциацию Расширения файлов ".svclog" и ".stvproj" с SvcTraceViewer.exe

/ отменить регистрацию: отменить регистрацию ассоциация расширений файлов ".svclog" и ".stvproj" с SvcTraceViewer.exe

1.При запуске Service Trace Viewer нажмите «Файл» и выберите «Открыть». Перейдите к месту, где ваш файлы трассировки сохраняются.

2. Дважды щелкните файл трассировки, который вы хотите открыть.

Примечание: нажмите SHIFT, нажимая несколько файлов трассировки для выбора и открыть их одновременно. обслуживание Trace Viewer объединяет содержимое всех файлы и представляет один вид. За Например, вы можете открыть файлы трассировки и клиент и сервис. Это полезно, когда вы включили сообщение регистрация и распространение активности в конфигурации. Таким образом, вы можете изучить обмен сообщениями между клиент и сервис. Вы также можете перетащить несколько файлов в средство просмотра или использовать вкладка Проект. Смотрите Управляющий Раздел проекта для более подробной информации.

3.Чтобы добавить дополнительные файлы трассировки в открытую коллекцию, нажмите Файл и затем укажите Добавить. В окне что открывается, перейдите к месту файлов трассировки и двойной щелчок файл, который вы хотите добавить.

Также, что касается фильтрации файла журнала, мы нашли эту ссылку чрезвычайно полезной:

http://msdn.microsoft.com/en-us/library/ms751526.aspx

2 голосов
/ 23 января 2009

Вот полезный метод для эффективной отладки / отслеживания триггеров. Это позволяет вам регистрировать все действия триггера вместе с элементом, на который воздействуют:

http://www.wpfmentor.com/2009/01/how-to-debug-triggers-using-trigger.html

1 голос
/ 15 мая 2014

Для тех, кто, как я, ищет чистый программный способ включения трассировки 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;
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...