Development Tip

손상된 WPF 데이터 바인딩을 감지하는 방법은 무엇입니까?

yourdevel 2020. 11. 1. 18:46
반응형

손상된 WPF 데이터 바인딩을 감지하는 방법은 무엇입니까?


근처에있는 질문에 답을 시도하는 동안 ' Unit Testing WPF Bindings '다음과 같은 질문이있었습니다.
WPF 데이터 바인딩 배선 설정이 잘못되었는지 확인하는 가장 좋은 방법은 무엇입니까? ?

단위 테스트 접근 방식은 Joel의 '파편을 제거하기 위해 팔을 떼어내는 것'처럼 보이지만 .. 나는 이것을 감지하는 더 쉬운 오버 헤드 방법을 찾고 있습니다.

모두가 WPF를 사용하여 데이터 바인딩에 크게 헌신 한 것처럼 보이며 장점이 있습니다.


.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의 출력 창에 특정 바인딩에 대한 추적 정보 만 저장됩니다.


내가 찾을 수있는 최고의 ...

WPF 바인딩을 어떻게 디버깅 할 수 있습니까? 작성자 : Beatriz Stollnitz

모든 사람이 바인딩 오류를 찾기 위해 항상 출력 창을 한 눈에 볼 수는 없기 때문에 옵션 # 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')

WPF Inspector의 트리거 디버깅 기능을 사용할 수 있습니다. codeplex에서 도구를 다운로드하고 실행중인 앱에 연결하기 만하면됩니다. 또한 창 하단에 바인딩 오류가 표시됩니다. 매우 유용한 도구!

여기에 이미지 설명 입력


여기에 제시된 솔루션을 사용하여 바인딩 오류를 기본 예외로 전환합니다. http://www.jasonbock.net/jb/Default.aspx?blog=entry.0f221e047de740ee90722b248933a28d

그러나 WPF 바인딩의 일반적인 시나리오는 사용자 입력을 대상 유형으로 변환 할 수없는 경우 (예 : 정수 필드에 바인딩 된 TextBox; 숫자가 아닌 문자열을 입력하면 FormatException이 발생하고 너무 큰 숫자를 입력하면 OverflowException이 발생 함). 비슷한 경우는 소스 속성의 Setter가 예외를 throw하는 경우입니다.

이를 처리하는 WPF 방법은 ValidatesOnExceptions = true 및 ValidationExceptionRule을 통해 제공된 입력이 올바르지 않음을 사용자에게 알리는 것입니다 (예외 메시지 사용).

그러나 이러한 예외는 출력 창으로도 전송되므로 BindingListener에 의해 '포착'되어 오류가 발생합니다 ... 분명히 원하는 동작이 아닙니다.

따라서 BindingListener다음과 같은 경우 예외를 throw하지 않도록 클래스를 확장했습니다 .

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 에서 수정 된 줄은 void WriteLine (string message)를 재정의합니다 .

        ....
        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


This was very helpful to us but I wanted to add to those who find this useful that there is a utility that Microsoft provides with the sdk to read this file.

Found here: http://msdn.microsoft.com/en-us/library/ms732023.aspx

To open a trace file

1.Start Service Trace Viewer by using a command window to navigate to your WCF installation location (C:\Program Files\Microsoft SDKs\Windows\v6.0\Bin), and then type SvcTraceViewer.exe. (although we found ours in \v7.0\Bin)

Note: The Service Trace Viewer tool can associate with two file types: .svclog and .stvproj. You can use two parameters in command line to register and unregister the file extensions.

/register: register the association of file extensions ".svclog" and ".stvproj" with SvcTraceViewer.exe

/unregister: unregister the association of file extensions ".svclog" and ".stvproj" with SvcTraceViewer.exe

1.When Service Trace Viewer starts, click File and then point to Open. Navigate to the location where your trace files are stored.

2.Double-click the trace file that you want to open.

Note: Press SHIFT while clicking multiple trace files to select and open them simultaneously. Service Trace Viewer merges the content of all files and presents one view. For example, you can open trace files of both client and service. This is useful when you have enabled message logging and activity propagation in configuration. In this way, you can examine message exchange between client and service. You can also drag multiple files into the viewer, or use the Project tab. See the Managing Project section for more details.

3.To add additional trace files to the collection that is open, click File and then point to Add. In the window that opens, navigate to the location of the trace files and double-click the file you want to add.

Also, as for the filtering of the log file, we found these this link extremely helpful:

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


For anyone like me looking for a pure programmatic way of enabling all WPF Tracing at a given Trace Level, here is a piece of code that does it. For reference, it's based on this article: Trace sources in WPF.

It doesn't requires a change in the app.config file, and it does not require to change the registry either.

This is how I use it, in some startup place (App, etc.):

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

And here is the utility code (by default it sends all Warning to the Default Trace Listener):

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

참고 URL : https://stackoverflow.com/questions/337023/how-to-detect-broken-wpf-data-binding

반응형