I don't know for sure, but I suspect it's because there's nowhere to handle the exception.
Suppose you have something whose properties you want to bind to, but sometimes that something is null. (For example, {Binding Name.Length}
, where Name is a string property that might be null.) In this case you're happy for this to be a no-op, because you know the control will never be shown when the Name is null (due to a trigger say) or because you know this will be a transient condition while the binding source is loading its data.
Now suppose WPF propagated the NullReferenceException when trying to call Length on the null Name string. In procedural code, you'd catch this exception and swallow it because you knew it was benign. But you don't get to put an exception handler around the WPF binding code. It's called from somewhere deep inside WPF. So the exception would bubble all the way up to Application.Run, which is not a very useful place to catch it.
So rather than making you centralise your binding exception handlers all the way up in Application.Run, I think the WPF guys decided to swallow the exceptions themselves. Only a theory though...