WPF中的Data Binding調(diào)試指南

大家平時(shí)做WPF開發(fā),相信用Visual studio的小伙伴比較多。XAML里面曾經(jīng)在某些特殊版本的Visual Studio中是可以加斷點(diǎn)進(jìn)行調(diào)試的,不過目前多數(shù)版本都不支持在XAML加斷點(diǎn)來調(diào)試。

那如果自己需要綁定的 Property 沒生效,該怎么去檢測(cè)或Debug排查問題呢?下面大白給出幾種自己用過的方法,本人的開發(fā)環(huán)境是 Win10專業(yè)版x64 + Visual Studio 2019專業(yè)版v16.2.2,以下方法都親測(cè)有效。


方法1: 修改注冊(cè)表 + 修改config文件

在注冊(cè)表中增加一個(gè)選項(xiàng),

具體做法是,在目錄HKEY_CURRENT_USER\Software\Microsoft中創(chuàng)建文件夾Tracing, 然后在其里面創(chuàng)建子文件夾WPF,然后新建一個(gè)DWORD(32位)值ManagedTracing,將其值設(shè)置為1.

1592713525851

也可以將下面的文件另存為 trace.reg,然后雙擊進(jìn)行設(shè)置。

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Microsoft\Tracing\WPF]
"ManagedTracing"=dword:00000001

接下來,需要在你的Project的能影響 .exe.config生成的那個(gè) .config文件下加入折疊區(qū)域的內(nèi)容:

1592713910975

由于我這邊相關(guān)的config文件就是App.config,所以只需在App.config中加入該內(nèi)容。

圖中折疊的部分如下:

  <system.diagnostics>
    <sources>
      <source name="System.Windows.Data" switchName="BindingSwitch" >
        <listeners>
          <add name="BindingTextListener" />
        </listeners>   
      </source>
      
       <!--<source name="System.Windows.Data" switchName="BindingSwitch" >
        <listeners>
          <add name="BindingXmlListener" />
        </listeners>      
      </source>-->

      <source name="System.Windows.DependencyProperty" switchName="BindingSwitch" >
        <listeners>
          <add name="BindingTextListener" />
        </listeners>
      </source>

      <source name="System.Windows.Freezable" switchName="BindingSwitch" >
        <listeners>
          <add name="BindingTextListener" />
        </listeners>
      </source>

      <source name="System.Windows.RoutedEvent" switchName="BindingSwitch" >
        <listeners>
          <add name="BindingTextListener" />
        </listeners>
      </source>

      <source name="System.Windows.Media.Animation" switchName="BindingSwitch" >
        <listeners>
          <add name="BindingTextListener" />
        </listeners>
      </source>

      <source name="System.Windows.NameScope" switchName="BindingSwitch" >
        <listeners>
          <add name="BindingTextListener" />
        </listeners>
      </source>

      <source name="System.Windows.ResourceDictionary" switchName="BindingSwitch" >
        <listeners>
          <add name="BindingTextListener" />
        </listeners>
      </source>

      <source name="System.Windows.Markup" switchName="BindingSwitch" >
        <listeners>
          <add name="BindingTextListener" />
        </listeners>
      </source>

      <source name="System.Windows.Documents" switchName="BindingSwitch" >
        <listeners>
          <add name="BindingTextListener" />
        </listeners>
      </source>
      
    </sources>
      
    <switches>
      <add name="BindingSwitch" value="All" />
      <!--add name="BindingSwitch" value="Off" -->
      <!--add name="BindingSwitch" value="Verbose" -->
      <!--add name="BindingSwitch" value="Warning" -->
      <!--add name="BindingSwitch" value="Activity" -->
    </switches>
    <sharedListeners>
      <!-- This listener sends output to a file named BindingTrace.log (text) -->
      <add name="BindingTextListener" type="System.Diagnostics.TextWriterTraceListener" initializeData="BindingTrace.log" />

      <!-- This listener sends output to the console -->
      <add name="console" type="System.Diagnostics.ConsoleTraceListener" initializeData="false"/>

      <!-- This listener sends output to an Xml file named BindingTrace.xml -->
      <add name="BindingXmlListener" type="System.Diagnostics.XmlWriterTraceListener" traceOutputOptions="None" initializeData="BindingTrace.xml" />
    </sharedListeners>

    <trace autoflush="true" indentsize="4"></trace>
  </system.diagnostics>

設(shè)置好后,你build這個(gè)wpf項(xiàng)目后,當(dāng)啟動(dòng)Debug時(shí),在其相應(yīng)的debug目錄下會(huì)多出一個(gè) BindingTrace.log文件,比如, 我這邊的內(nèi)容上這樣的:

1592714137479

我配置監(jiān)聽器(listener)時(shí),將debug的信息設(shè)置成了.log格式,與.txt格式相比其優(yōu)勢(shì)是: 當(dāng)用vs code打開時(shí),自帶高亮,看起來比較爽。

      <!-- This listener sends output to a file named BindingTrace.log (text) -->
      <add name="BindingTextListener" type="System.Diagnostics.TextWriterTraceListener" initializeData="BindingTrace.log" />

當(dāng)然也有小伙伴希望將Trace信息導(dǎo)出為xml,也可以的,只需將加入內(nèi)容開頭部分的:

  <source>
    <listeners>
      <add name="BindingTextListener" />
    </listeners>   
  </source>
  
   <!--<source name="System.Windows.Data" switchName="BindingSwitch" >
    <listeners>
      <add name="BindingXmlListener" />
    </listeners>
      </source>  -->

改為:

  <!-- <source>
    <listeners>
      <add name="BindingTextListener" />
    </listeners>   
  </source> -->
  
   <source name="System.Windows.Data" switchName="BindingSwitch" >
    <listeners>
      <add name="BindingXmlListener" />
    </listeners>
   </source>

即可。

那么,此時(shí)在其相應(yīng)的debug目錄下會(huì)多出一個(gè) BindingTrace.xml文件,我這邊的內(nèi)容上這樣的:

1592714724096

參考:

https://systemscenter.ru/scsm_authoringtool.en/html/b24efd85-0ced-48ea-8ecc-d816c789bae2.htm

https://www.cnblogs.com/furenjun/archive/2011/08/01/2123983.html

WPF Tutorial | Debug DataBinding Issues
https://www.wpftutorial.net/DebugDataBinding.html

old-wpf-blog/45-DebuggingDataBinding at master · bstollnitz/old-wpf-blog
https://github.com/bstollnitz/old-wpf-blog/tree/master/45-DebuggingDataBinding

方法2: 在XAML中設(shè)置TraceLevel + 在xaml中需要debug的View對(duì)應(yīng)的 .xaml.cs文件中啟用WPF Trace

該方法適用于 .NET framework 3.5以后(包括 .NET core)的WPF project.

首先需要給該View的xaml文件的某個(gè)節(jié)點(diǎn)加入PresentationTraceSources.TraceLevel="High",

<UserControl x:Class="CaliburnMicro_Calculator.Views.CalculatorView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:local="clr-namespace:CaliburnMicro_Calculator.Views"
             xmlns:cal="http://www.caliburnproject.org"
             mc:Ignorable="d"
             Width="240">

我這邊直接在這個(gè)view的根節(jié)點(diǎn)<UserControl>中加入PresentationTraceSources.TraceLevel="High",結(jié)果如下:

<UserControl x:Class="CaliburnMicro_Calculator.Views.CalculatorView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:local="clr-namespace:CaliburnMicro_Calculator.Views"
             xmlns:cal="http://www.caliburnproject.org"
             mc:Ignorable="d"
             Width="240" PresentationTraceSources.TraceLevel="High">

此時(shí),我們還需要在目標(biāo)View的對(duì)應(yīng)的 .xaml.cs文件中啟用WPF Trace.

            // Enable WPF tracing
            PresentationTraceSources.Refresh();
            PresentationTraceSources.DataBindingSource.Listeners.Add(new ConsoleTraceListener());
            PresentationTraceSources.DataBindingSource.Switch.Level = SourceLevels.All;

此時(shí),在Output(輸出窗口)就可以看到數(shù)據(jù)綁定的相關(guān)信息了。

1592715540437-大白技術(shù)控

可能有人會(huì)好奇output中的紅色字體是怎么來的,vs的output默認(rèn)是黑色。

其實(shí)安裝一個(gè)vs插件VSColorOutput就好了,傳送門:

https://marketplace.visualstudio.com/items?itemName=MikeWard-AnnArbor.VSColorOutput.

當(dāng)然,你還可以在此時(shí)啟用"診斷工具",位置是: 調(diào)試 -> 窗口 -> 顯示診斷工具,配合起來用起來更爽喔~

1592715463451

方法3: Visual Studio 2019 (16.4之后的版本)安裝 XAML binding extension

這個(gè)VS插件由微軟XAML團(tuán)隊(duì)推出,看起來像是實(shí)現(xiàn)了方法1或方法2的自動(dòng)化。

XAML binding extension for Visual Studio 2019 下載地址:
https://marketplace.visualstudio.com/items?itemName=PeterSpa.XamlBinding

相關(guān)代碼已開源:

spadapet/xaml-binding-tool: XAML binding error window in a Visual Studio 2019 extension
https://github.com/spadapet/xaml-binding-tool

當(dāng)安裝好這個(gè)插件時(shí),重啟VS就可以用了,debug時(shí),調(diào)試窗口中會(huì)多一個(gè)選項(xiàng)"XAML binding failures (experimental)"。點(diǎn)擊該選項(xiàng),debug相關(guān)窗口中會(huì)顯示Data binding的詳細(xì)信息。

1592716073429-大白技術(shù)控

此時(shí),WPF trace level附近的...還可以點(diǎn)擊進(jìn)行設(shè)置。

1592715986388-大白技術(shù)控

方法4: 使用第三方debug工具 WPF

首推Snoop,這個(gè)工具大概2006年就出來了,歷史悠久,最初由微軟Blend團(tuán)隊(duì)的Pete Blois開發(fā),功能也異常強(qiáng)大,而且目前也一直有人維護(hù)和更新。

1592826132129

左上角支持filter,屬性或?qū)蛹?jí)很多時(shí),可以快速定位目標(biāo)節(jié)點(diǎn)。

Snoop中的Tree, Properties, Data Context均支持filter,而Properties和Data Context都可以打斷點(diǎn)。

當(dāng)屬性值更改,整個(gè)屬性的背景更改為黃色高亮一秒鐘,以吸引用戶注意。

Snoop允許您查看您在應(yīng)用程序中指定的事件列表。當(dāng)您單擊元素時(shí),您可以看到哪些元素受到影響,并查看哪個(gè)(方法或任何人)處理該點(diǎn)擊。Hanlded的事件以綠色顯示。這是Snoop提供的查看隧道和事件冒泡傳遞之間的區(qū)別的強(qiáng)有力方法,特別是當(dāng)這些事件處理得太快或根本不處理,它們?nèi)绾斡绊懩目梢暬亍?/p>

當(dāng)出現(xiàn)binding error時(shí),可以選擇應(yīng)用程序右側(cè)的屬性,然后右鍵單擊以深入了解綁定或綁定表達(dá)式,以便給出更詳細(xì)的錯(cuò)誤說明。

在Snoop的左上角,有一個(gè)下拉框可以打開,然后選擇"Show only Visuals with binding Errors"以查看應(yīng)用程序所具有的可視數(shù)據(jù)綁定錯(cuò)誤列表。

img

Snoop 的一個(gè)眾所周知的功能是能夠識(shí)別數(shù)據(jù)綁定問題。當(dāng)看到組件是否綁定正確時(shí),我通常只是嘗試一下,看看它是否有效。如果無效,我轉(zhuǎn)向 Visual Studio 調(diào)試模式下的output窗口。如果無法立即看到該值,我會(huì)這樣做:將 Snoop 附加(Attach)到我的應(yīng)用,并從應(yīng)用程序樹視圖上方的搜索/篩選器欄中選擇"Show only visuals with binding errors"選項(xiàng)。

Attach和Debug的步驟如下:

  • 以管理員權(quán)限啟動(dòng)snoop
  • 在代碼里面的合適地方加上斷點(diǎn)
  • Ctrl + F5 運(yùn)行項(xiàng)目
  • 重現(xiàn)需要debug的界面
  • 調(diào)試 -> Debug -> 附加到進(jìn)程(Attach)

然后在snoop上依次點(diǎn):

Refresh按鈕, Snoop按鈕(望遠(yuǎn)鏡),借助filter找需要inspect的目標(biāo)元素,接下來 debug就比較順暢了。

還可以使用它來顯示任何具有綁定錯(cuò)誤(Binding error)的控件(就像word中的拼寫檢查一樣):

大白技術(shù)控-snoop綁定

Snoop 中的綁定錯(cuò)誤會(huì)紅色高亮顯示

也有小伙伴在用或WPF Inspector,不過這個(gè)工具好久沒更新了。


WPF inspect-大白技術(shù)控

WPF Inspector 這個(gè)項(xiàng)目之前是在CodePlex上的,后來沒人維護(hù)了,目前有人手動(dòng)fork到github上,但沒見任何更新。

還有小伙伴用 Mole這個(gè)Visual Studio 插件,有興趣的朋友可以去試試~

Mole for Visual Studio插件下載:

Mole for VS 2015 is installed from the Visual Studio Marketplace.

Mole for VS 2017 is installed from the Visual Studio Marketplace.

Mole for VS 2019 is installed from the Visual Studio Marketplace.

mole

其他方法:

  • Binding改為x:Binding后進(jìn)行調(diào)試
  • 增加一個(gè) ValueConverter,調(diào)用它進(jìn)行調(diào)試

這兩種本人不太熟悉,有興趣的可以自己去試試哈~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容