How can I figure out what line of xaml contains the troublesome binding When my debug output is full of lines like the following:
System.Windows.Data Error: 5 : Value produced by BindingExpression is not valid for target property.; Value='UW.Entities.ProgramModel.UWProgram' BindingExpression:Path=; DataItem='RuntimeType' (HashCode=24995901); target element is 'DataGridCollectionViewSource' (HashCode=60976864); target property is 'Source' (type 'Object')
I don't know how to interpret this in a way that can let me find the responsible line of xaml. I can't even figure out what xaml file the error is coming from. Is there some way to get more information when these errors occur?
'UW.Entities.ProgramModel.UWProgram' is just a type - I don't know what the object being bound to is. I also have lots of DataGridCollectionViewSources in various bits of xaml, all who's property 'Source' is bound to something which may or may not have that type (again - no easy way to tell).
For WPF in . NET Framework, data binding failures must be shown in the debug output for the XAML Binding Failures pane to detect and show them. The option for this is in the Tools > Options > Debugging > Output Window > WPF Trace Settings dialog.
A binding source is usually a property on an object so you need to provide both the data source object and the data source property in your binding XAML. In the above example the ElementName attribute signifies that you want data from another element on the page and the Path signifies the appropriate property.
If you do not know which binding fails
I would use the Snoop utility for this purposes. In short - at the top-left corner above the visual tree, you'll find a drop-down list which allows filtering visuals, just select Visuals with binding Error. See online documentation for more details.
If you know which binding fails
Sometime you know which binding fails but was not able to find a source fo the problem since binding is pretty tricky, for instance TemplateBindings, bindings which refer to a DataContext of another control, etc.. I found helpful putting a TextBlock
which Text property is bound to the same binding source in this way you can see what exactly bound since TextBlock will display a type name of a bound object.
For instance you have following failed binding:
<ItemsControl ItemsSource="{Binding Parent.DataContext.ActiveItem.DataContext}" /> <!-- See what is bound, if failed - try previous level --> <TextBlock Text="{Binding Parent.DataContext}" /> <TextBlock Text="{Binding Parent.Inner.Items}" /> <TextBlock Text="{Binding Parent.Inner}" />
Useful links:
I have been happily using the wonderful snippet from 'Switch on the Code' to detect and report binding errors since it was first published in 2009...
http://www.switchonthecode.com/tutorials/wpf-snippet-detecting-binding-errors
edit: still works excellently on VS2012 (Sept 2013)
The link appears broken, so I'll paste in the relevant snippets...
using System.Diagnostics; using System.Text; using System.Windows; namespace SOTC_BindingErrorTracer { public class BindingErrorTraceListener : DefaultTraceListener { //http://www.switchonthecode.com/tutorials/wpf-snippet-detecting-binding-errors private static BindingErrorTraceListener _Listener; public static void SetTrace() { SetTrace(SourceLevels.Error, TraceOptions.None); } public static void SetTrace(SourceLevels level, TraceOptions options) { if (_Listener == null) { _Listener = new BindingErrorTraceListener(); PresentationTraceSources.DataBindingSource.Listeners.Add(_Listener); } _Listener.TraceOutputOptions = options; PresentationTraceSources.DataBindingSource.Switch.Level = level; } public static void CloseTrace() { if (_Listener == null) { return; } _Listener.Flush(); _Listener.Close(); PresentationTraceSources.DataBindingSource.Listeners.Remove(_Listener); _Listener = null; } private StringBuilder _Message = new StringBuilder(); private BindingErrorTraceListener() { } public override void Write(string message) { _Message.Append(message); } public override void WriteLine(string message) { _Message.Append(message); var final = _Message.ToString(); _Message.Length = 0; MessageBox.Show(final, "Binding Error", MessageBoxButton.OK, MessageBoxImage.Error); } } }
And to set it up/initialize it...
namespace WpfListeningForTraceErrors { /// <summary> /// Interaction logic for Window1.xaml /// </summary> public partial class Window1 : Window { public Window1() { BindingErrorTraceListener.SetTrace(); InitializeComponent(); } } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With