Today I found rather strange problem.
I was getting strange exception from MS internal code related to bindings.
The exception was raised when code was trying to set SelectedItem of DataGrid control.
Stack Trace is very large but most important lines are as follows:
Message: Object reference not set to an instance of an object.
ExceptionType: System.NullReferenceException
Details
at MS.Internal.Data.PropertyPathWorker.DetermineWhetherDBNullIsValid(Object item)
at MS.Internal.Data.PropertyPathWorker.DetermineWhetherDBNullIsValid()
at MS.Internal.Data.PropertyPathWorker.get_IsDBNullValidForUpdate()
at MS.Internal.Data.ClrBindingWorker.get_IsDBNullValidForUpdate()
at System.Windows.Data.BindingExpression.ConvertProposedValue(Object value)
at System.Windows.Data.BindingExpressionBase.UpdateValue()
at System.Windows.Data.BindingExpression.UpdateOverride()
at System.Windows.Data.BindingExpressionBase.Update()
at System.Windows.Data.BindingExpressionBase.Dirty()
at System.Windows.Data.BindingExpressionBase.SetValue(DependencyObject d, DependencyProperty dp, Object value)
at System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp, Object value, PropertyMetadata metadata, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType, Boolean isInternal)
at System.Windows.DependencyObject.SetValue(DependencyProperty dp, Object value)
at MyNamespace.BusinessDataGrid.set_SelectedItem(Object value)
I could not understand the reason so I started to dig inside MS code using Reflector.
After some time I noticed the following piece of code inside method causing error:
private bool DetermineWhetherDBNullIsValid(object item) { PropertyInfo info; PropertyDescriptor descriptor; DependencyProperty property; DynamicPropertyAccessor accessor; this.SetPropertyInfo(this._arySVS[this.Length - 1].info, out info, out descriptor, out property, out accessor); string columnName = (descriptor != null) ? descriptor.Name : ((info != null) ? info.Name : null); object arg = ((columnName == "Item") && (info != null)) ? this._arySVS[this.Length - 1].args[0] : null; return SystemDataHelper.DetermineWhetherDBNullIsValid(item, columnName, arg); }
I assumed this could be problem – args of PropertyInfo where null.
It seems MS have hardcoded name “Item” as indexed property and assumed no one will ever name CLR property with “Item”.
After that I found the binding which was causing this code to execute:
Once commented everything worked fine.
To replicate the problem use this code:
public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); SetBinding(TagProperty, new Binding("Item") { RelativeSource = RelativeSource.Self, Mode = BindingMode.TwoWay, }); Tag = 1; Tag = null; } public object Item { get; set; } }
To summarize – the rule to keep in mind – don’t name CLR property with name “Item” if you may use it in binding
Happy Coding
Kirill