WPF XPath binding with multiple results converted to comma delimited string

I have an XML file similar in structure to the following:

<Parent>
<Child>5</Child>
<Child>3</Child>
<Child>5</Child>
<Child>1</Child>
</Parent>

In my XAML, I have a ListView associated with an XML file and associated with a DataTemplate ListViewItem as follows:

<TextBlock Text="{Binding XPath=Parent/Child}"/>

Obviously, I expect 4 results for this XPath query, but I can’t find a way to convert the results to comma delimited strings, and right now TextBlock just displays the first value.

If I use the same XPath query to set the ItemsSource ListBox, I get all the results in the ListBox, so I think I should get all the values ​​passed to the Converter class ...

+4
source share
2 answers

There is no way to get an XPath request that returns multiple nodes, for example yours, will combine them into a single value for you. What happens is that the node node is returned, and as you bind to a single string property, the infrastructure simply tidies up this set of nodes, grabbing the first node from the set and grabbing its @text node.

Honestly, I have not tried this myself and do not have time at the moment, but the only way I would expect to ever work is to write my own IValueConverter. I assume that it will pass the XmlNodeList as the value to be converted, and then you can list these nodes and merge the string separated by a comma yourself.

Update

Since the IValueConverter clause did not work because the XPath engine does pre-coercion, here's what I suggest to you: instead of binding to a single text block, snap to the ItemsControl instead and define the ItemTemplate for ItemsControl as follows:

 <DataTemplate> <TextBlock Text="{Binding}"/>, </DataTemplate> 

Note: to be honest, I take the lazy approach in the DataTemplate and you will get a comma even after the last item right now. In doing so, you must define a DataTemplate with a trigger that determines that this is the last item and does not show a comma.

Finally, depending on how you want the data in the layout to also set the ItemsControl ItemsPanel. I assume you want horizontal flow with packaging here:

 <ItemsPanelTemplate> <WrapPanel Orientation="Horizontal" /> </ItemsPanelTemplate> 
+1
source

If you want to set the XML data as a source in a ListView, you can do it like this:

 MyListView.ItemsSource = XElement.Load(@"XMLFile1.xml").Elements("Child"); 

and you bind to the Value property in the TextBlock:

 <TextBlock Text="{Binding Path=Value}" /> 

If you need to modify the request, you can extract the contents of your XML file in var, which you can use as the ItemsSource in the ListView.

 XElement xmlData = XElement.Load(@"XMLFile1.xml"); var query = from x in xmlData.Elements("Child") select x; 
0
source

All Articles