While trying to answer a question in the vicinity 'Unit Testing WPF Bindings' I had the following niggling question..
What's the best way to find if you have WPF Data Binding wiring setup incorrectly (or you just broke something that was wired up correctly) ?
在尝试回答附近的“单元测试WPF绑定”问题时,我有一个小问题。如果WPF数据绑定连接设置不正确(或者您只是破坏了正确连接的东西),最好的方法是什么?
Although the unit-testing approach seems to be like Joel's 'ripping off your arm to remove a splinter'.. I am looking around for easier less Overhead ways to detect this.
尽管这种单元测试方法看起来就像乔尔的“撕掉你的手臂来移除碎片”一样。我正在寻找更简单、开销更少的方法来检测这一点。
Everyone seems to have committed themselves to data binding in a big way with WPF.. and it does have its merits.
每个人似乎都致力于与WPF进行大规模的数据绑定。它确实有它的优点。
7 个解决方案
#1
64
In .NET 3.5 it was introduced a new way to specifically output tracing information about specific data bindings.
This is done through the new System.Diagnostics.PresentationTraceSources.TraceLevel attached property that you can apply to any binding or data provider. Here is an example:
在。net 3.5中,引入了一种新的方法来具体地输出关于特定数据绑定的跟踪信息。这是通过新的系统来实现的。可以应用于任何绑定或数据提供程序的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>
This will put trace information for just that particular binding in Visual Studio's Output Window, without any tracing configuration required.
这将在Visual Studio的输出窗口中为特定的绑定放置跟踪信息,而不需要任何跟踪配置。
#2
38
Best I could find...
我能找到的最好的…
How can I debug WPF Bindings? by Beatriz Stollnitz
Since everyone can't always keep one eye on the Output Window looking for Binding errors, I loved Option#2. Which is add this to your App.Config
因为每个人都不能总是盯着输出窗口寻找绑定错误,所以我喜欢选项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>
Pair that up with a good regex scan script to extract out relevant info, that you can run occasionally on the GraveOfBindErrors.txt in your output folder
将其与一个好的regex扫描脚本进行配对,以提取相关信息,您可以偶尔在gravofbinderrors上运行这些信息。输出文件夹中的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')
#3
5
You can use the trigger debugging feature of WPF Inspector. Just download the tool from codeplex and attach it to your running app. It also shows binding errors on the bottom of the window. Very useful tool!
您可以使用WPF检查器的触发器调试特性。只需从codeplex上下载这个工具,并将它附加到你正在运行的应用上。非常有用的工具!
#4
4
I use the solution presented here to turn binding errors into native Exceptions: http://www.jasonbock.net/jb/Default.aspx?blog=entry.0f221e047de740ee90722b248933a28d
我使用这里提供的解决方案将绑定错误转换为本地异常:http://www.jasonbock.net/jb/default.aspx?
However, a normal scenario in WPF bindings is to throw exceptions in case the user input cannot be converted to the target type (for instance, a TextBox bound to a integer field; the input of a non-numeric string results in a FormatException, the input of number that is too large results in an OverflowException). A similar case is when the Setter of the source property throws an exception.
然而,WPF绑定中的一个常规场景是在用户输入不能转换为目标类型时抛出异常(例如,绑定到整数字段的文本框;非数字字符串的输入导致了一个FormatException,这个输入的数字太大导致了溢出异常。类似的情况是源属性的Setter抛出异常。
The WPF way of handling this is via ValidatesOnExceptions=true and ValidationExceptionRule to signal the user the supplied input is not correct (using the exception message).
WPF处理这个问题的方法是通过validatesonexception =true和ValidationExceptionRule来通知用户提供的输入不正确(使用异常消息)。
However, these exception are also send to the output window and thus 'caught' by the BindingListener, resulting in an error...clearly not the behaviour you'd want.
但是,这些异常也会发送到输出窗口,从而被BindingListener“捕获”,导致错误…显然不是你想要的那种行为。
Therefore, I expanded the BindingListener
class to NOT throw an Exception in these cases:
因此,我扩展了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"
};
Modified lines in public override void WriteLine(string message):
修改的行在公共覆盖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
2
Here's a useful technique for debugging/tracing triggers effectively. It allows you to log all trigger actions along with the element being acted upon:
下面是一种有效调试/跟踪触发器的有用技术。它允许您记录所有的触发器动作以及正在执行的元素:
http://www.wpfmentor.com/2009/01/how-to-debug-triggers-using-trigger.html
http://www.wpfmentor.com/2009/01/how-to-debug-triggers-using-trigger.html
#6
2
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.
这对我们很有帮助,但我想补充的是,对于那些发现这个有用的人来说,有一个实用工具是Microsoft提供给sdk来读取这个文件的。
Found here: http://msdn.microsoft.com/en-us/library/ms732023.aspx
在这里找到: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)
1。使用命令窗口启动服务跟踪查看器,导航到WCF安装位置(C:\程序文件\Microsoft SDKs\Windows\v6.0\Bin),然后输入svctraceview .exe。(虽然我们在\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.
注意:服务跟踪查看器工具可以关联两个文件类型:.svclog和.stvproj。您可以在命令行中使用两个参数来注册和注销文件扩展名。
/register: register the association of file extensions ".svclog" and ".stvproj" with SvcTraceViewer.exe
/注册:注册文件扩展名的关联。svclog”和“。与SvcTraceViewer.exe stvproj”
/unregister: unregister the association of file extensions ".svclog" and ".stvproj" with SvcTraceViewer.exe
/unregister: unregister the association of file extensions "。svclog”和“。与SvcTraceViewer.exe stvproj”
1.When Service Trace Viewer starts, click File and then point to Open. Navigate to the location where your trace files are stored.
1。当服务跟踪查看器启动时,单击File,然后指向Open。导航到存储跟踪文件的位置。
2.Double-click the trace file that you want to open.
2。双击要打开的跟踪文件。
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.
注意:单击多个跟踪文件时按SHIFT,同时选择和打开它们。服务跟踪查看器合并所有文件的内容并显示一个视图。例如,您可以同时打开客户端和服务的跟踪文件。当您在配置中启用消息日志记录和活动传播时,这是非常有用的。通过这种方式,您可以检查客户机和服务之间的消息交换。您还可以将多个文件拖放到查看器中,或者使用Project选项卡。有关更多细节,请参见管理项目一节。
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.
3所示。要向打开的集合添加其他跟踪文件,请单击File,然后指向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
http://msdn.microsoft.com/en-us/library/ms751526.aspx
#7
1
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.
对于像我这样正在寻找在给定的跟踪级别上启用所有WPF跟踪的纯编程方式的人来说,这里有一段代码可以实现这一点。作为参考,本文基于WPF中的跟踪源。
It doesn't requires a change in the app.config file, and it does not require to change the registry either.
它不需要修改app.config文件,也不需要修改注册表。
This is how I use it, in some startup place (App, etc.):
在一些初创公司(App等),我就是这样使用它的:
....
#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;
}
}
}
#1
64
In .NET 3.5 it was introduced a new way to specifically output tracing information about specific data bindings.
This is done through the new System.Diagnostics.PresentationTraceSources.TraceLevel attached property that you can apply to any binding or data provider. Here is an example:
在。net 3.5中,引入了一种新的方法来具体地输出关于特定数据绑定的跟踪信息。这是通过新的系统来实现的。可以应用于任何绑定或数据提供程序的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>
This will put trace information for just that particular binding in Visual Studio's Output Window, without any tracing configuration required.
这将在Visual Studio的输出窗口中为特定的绑定放置跟踪信息,而不需要任何跟踪配置。
#2
38
Best I could find...
我能找到的最好的…
How can I debug WPF Bindings? by Beatriz Stollnitz
Since everyone can't always keep one eye on the Output Window looking for Binding errors, I loved Option#2. Which is add this to your App.Config
因为每个人都不能总是盯着输出窗口寻找绑定错误,所以我喜欢选项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>
Pair that up with a good regex scan script to extract out relevant info, that you can run occasionally on the GraveOfBindErrors.txt in your output folder
将其与一个好的regex扫描脚本进行配对,以提取相关信息,您可以偶尔在gravofbinderrors上运行这些信息。输出文件夹中的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')
#3
5
You can use the trigger debugging feature of WPF Inspector. Just download the tool from codeplex and attach it to your running app. It also shows binding errors on the bottom of the window. Very useful tool!
您可以使用WPF检查器的触发器调试特性。只需从codeplex上下载这个工具,并将它附加到你正在运行的应用上。非常有用的工具!
#4
4
I use the solution presented here to turn binding errors into native Exceptions: http://www.jasonbock.net/jb/Default.aspx?blog=entry.0f221e047de740ee90722b248933a28d
我使用这里提供的解决方案将绑定错误转换为本地异常:http://www.jasonbock.net/jb/default.aspx?
However, a normal scenario in WPF bindings is to throw exceptions in case the user input cannot be converted to the target type (for instance, a TextBox bound to a integer field; the input of a non-numeric string results in a FormatException, the input of number that is too large results in an OverflowException). A similar case is when the Setter of the source property throws an exception.
然而,WPF绑定中的一个常规场景是在用户输入不能转换为目标类型时抛出异常(例如,绑定到整数字段的文本框;非数字字符串的输入导致了一个FormatException,这个输入的数字太大导致了溢出异常。类似的情况是源属性的Setter抛出异常。
The WPF way of handling this is via ValidatesOnExceptions=true and ValidationExceptionRule to signal the user the supplied input is not correct (using the exception message).
WPF处理这个问题的方法是通过validatesonexception =true和ValidationExceptionRule来通知用户提供的输入不正确(使用异常消息)。
However, these exception are also send to the output window and thus 'caught' by the BindingListener, resulting in an error...clearly not the behaviour you'd want.
但是,这些异常也会发送到输出窗口,从而被BindingListener“捕获”,导致错误…显然不是你想要的那种行为。
Therefore, I expanded the BindingListener
class to NOT throw an Exception in these cases:
因此,我扩展了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"
};
Modified lines in public override void WriteLine(string message):
修改的行在公共覆盖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
2
Here's a useful technique for debugging/tracing triggers effectively. It allows you to log all trigger actions along with the element being acted upon:
下面是一种有效调试/跟踪触发器的有用技术。它允许您记录所有的触发器动作以及正在执行的元素:
http://www.wpfmentor.com/2009/01/how-to-debug-triggers-using-trigger.html
http://www.wpfmentor.com/2009/01/how-to-debug-triggers-using-trigger.html
#6
2
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.
这对我们很有帮助,但我想补充的是,对于那些发现这个有用的人来说,有一个实用工具是Microsoft提供给sdk来读取这个文件的。
Found here: http://msdn.microsoft.com/en-us/library/ms732023.aspx
在这里找到: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)
1。使用命令窗口启动服务跟踪查看器,导航到WCF安装位置(C:\程序文件\Microsoft SDKs\Windows\v6.0\Bin),然后输入svctraceview .exe。(虽然我们在\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.
注意:服务跟踪查看器工具可以关联两个文件类型:.svclog和.stvproj。您可以在命令行中使用两个参数来注册和注销文件扩展名。
/register: register the association of file extensions ".svclog" and ".stvproj" with SvcTraceViewer.exe
/注册:注册文件扩展名的关联。svclog”和“。与SvcTraceViewer.exe stvproj”
/unregister: unregister the association of file extensions ".svclog" and ".stvproj" with SvcTraceViewer.exe
/unregister: unregister the association of file extensions "。svclog”和“。与SvcTraceViewer.exe stvproj”
1.When Service Trace Viewer starts, click File and then point to Open. Navigate to the location where your trace files are stored.
1。当服务跟踪查看器启动时,单击File,然后指向Open。导航到存储跟踪文件的位置。
2.Double-click the trace file that you want to open.
2。双击要打开的跟踪文件。
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.
注意:单击多个跟踪文件时按SHIFT,同时选择和打开它们。服务跟踪查看器合并所有文件的内容并显示一个视图。例如,您可以同时打开客户端和服务的跟踪文件。当您在配置中启用消息日志记录和活动传播时,这是非常有用的。通过这种方式,您可以检查客户机和服务之间的消息交换。您还可以将多个文件拖放到查看器中,或者使用Project选项卡。有关更多细节,请参见管理项目一节。
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.
3所示。要向打开的集合添加其他跟踪文件,请单击File,然后指向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
http://msdn.microsoft.com/en-us/library/ms751526.aspx
#7
1
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.
对于像我这样正在寻找在给定的跟踪级别上启用所有WPF跟踪的纯编程方式的人来说,这里有一段代码可以实现这一点。作为参考,本文基于WPF中的跟踪源。
It doesn't requires a change in the app.config file, and it does not require to change the registry either.
它不需要修改app.config文件,也不需要修改注册表。
This is how I use it, in some startup place (App, etc.):
在一些初创公司(App等),我就是这样使用它的:
....
#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;
}
}
}