views:

115

answers:

1

I'm binding DataTemplates to an XmlDataProvider. Since the XML data in question makes use of namespaces, I've also attached an XmlNamespaceManager to the XmlDataProvider and mapped a prefix to it.

When Binding to an XPath fresh off the root of the XmlDataProvider, the namespace prefix is understood just fine and I get results. However, if from within the DataTemplate I try to do another XPath based binding, the Output window shows this error at runtime:

Cannot obtain result node collection because of bad source node or bad Path.; SourceNode='IntegrationProfile'; Path='i:Role' BindingExpression:Path=; DataItem='XmlElement' (HashCode=19883454); target element is 'TabControl' (Name=''); target property is 'ItemsSource' (type 'IEnumerable') XPathException:'System.Xml.XPath.XPathException: Namespace Manager or XsltContext needed. This query has a prefix, variable, or user-defined function.

This error was provoked with this line of XAML:

<TabControl ItemsSource="{Binding XPath=i:Role}"/>

which is within a DataTemplate. The NamespaceManager was attached in code, like this:

_profile = new XmlDataProvider();
_profile.Document = new XmlDocument();
_profile.Document.Load(ProfilePath);
_profile.XmlNamespaceManager = NamespaceManager;

Is WPF forgetting that there's a NamespaceManager attached?

A: 

Found the reason and the solution myself.

Reason: The DataTemplate's DataContext is bound to the child element selected in the first query, and the scope doesn't "reach back" to where the NamespaceManager is attached.

Solution: Create an XmlNamespaceMappingCollection in the Resource block:

<Window.Resources>
    <XmlNamespaceMappingCollection x:Key="MyNamespaces">
        <XmlNamespaceMapping Uri="http://foo.com/MyNamespace" Prefix="i"/>
    </XmlNamespaceMappingCollection>
    ...
</Window.Resources>

Then put the following attribute in the parent element of whatever control is making XPath queries in its bindings:

Binding.XmlNamespaceManager="{StaticResource MyNamespaces}"

Putting it in the same element next to ItemSource="..." didn't work, but making it an attribute of the parent element did.

C. Lawrence Wenham