Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to locate the source of a binding error?

Tags:

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

like image 718
Alain Avatar asked Dec 12 '11 20:12

Alain


People also ask

How to find binding errors in WPF?

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.

What is binding source in WPF?

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.


2 Answers

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:

  • Debugging Data Bindings in a WPF or Silverlight Application
  • Nice trick using special DebugConverter which allows break a debugger whilst doing a binding, see Debugging WPF DataBinding article
like image 196
sll Avatar answered Dec 13 '22 01:12

sll


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)

Update 25 Jan 2016

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();         }     } } 
like image 28
Gayot Fow Avatar answered Dec 13 '22 01:12

Gayot Fow