Thursday, April 24, 2008

XAML+LoadComponent VS pure code - where are my name scopes???

Recently my coworker faced one interesting problem. He was looking through the sample for the Josh's article on 3D in WPF, and said that he had noticed one strange thing - whenever you try to replace the loading of the Viewport3D from XAML with in-code creation, you get an exception in RegisterName methods, saying that there is no name scope for the provided element.
So, what is the difference between loading XAML and creating element from code? I made a short research using the greatest tool in a .NET world, Reflector, and it turned out that in case when XamlReader (or, to be more specific, BamlRecordReader) meets some element, that does not support INameScope interface, it creates the namescope itself, and attaches it to the element (NameScope.SetNameScope(dependencyObject, new NameScope());).
Finally, to resolve the issue with an exception, we have manually created the NameScope and attached it to the viewport.
Also, XamlReader calls BeginInit and EndInit methods whenewer the loaded element supports ISupportInitialize interface. So you should remember to use that too when you create visual element in code.

2 comments:

Josh Smith said...

Just so you know, I posted a better version of the 3D panel that does not use the namescope hackery.

http://www.codeproject.com/KB/WPF/panel3d.aspx

Thanks,
Josh Smith

Rat's Blog said...

Thanks - great article...like all other your articles :)