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

При попытке ответить на вопрос в окрестности "Unit Testing WPF Bindings" У меня был следующий вопрос: Какой лучший способ найти, если у вас неправильно настроена проводка привязки данных WPF (или вы просто сломали что-то, что было правильно подключено)?

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

Кажется, что все привязаны к привязке данных с WPF.. и у него есть свои достоинства.

Ответ 1

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

Как я могу отлаживать привязки 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>

Сопоставьте это с хорошим просмотром регулярных выражений 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;
        }
    }
}