Как обнаружить сломанную привязку данных WPF?

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

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

все, похоже, взяли на себя обязательства по привязке данных с помощью WPF.. и в этом есть свои достоинства.

7 ответов


в .NET 3.5 был введен новый способ вывода информации трассировки о конкретных привязках данных.

Это делается через новый


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

как я могу отлаживать привязки WPF? по Беатрис Stollnitz

поскольку все не могут всегда следить за окном вывода, ища ошибки привязки, мне понравился вариант № 2. Что добавить это в приложение.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')

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

enter image description here


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

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

способ обработки 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();
            }
        }
    }

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

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


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

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

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

1.Запустите Service Trace Viewer с помощью окна команд для перехода к Расположение установки WCF (C:\Program Файлы\Microsoft Пакет SDK папке\Windows\V6 двигателем.0\Бин), а затем введите SvcTraceViewer.исполняемый. (хотя мы нашли наши в \v7.0\Bin)

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

/ register: Регистрация ассоциации расширение файла." svclog ПО" и ".stvproj " с SvcTraceViewer.exe

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

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

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

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

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

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

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


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

это не требует изменения в приложение.конфигурационный файл, и он также не требует изменения реестра.

вот как я его использую, в каком-то месте запуска (приложение и т. д.):

....
#if DEBUG
    WpfUtilities.SetTracing();
#endif
....

и вот код утилиты (by по умолчанию он отправляет все предупреждения Прослушивателю трассировки по умолчанию):

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