interesting question!
First of all, it seems like the XPaths you are using are not completely correct. If I understand you correctly, you want to display a ListBox with Countries, a ListBox with Areas and a TextBlock with Avg(areas)
.
First, let's simplify the XPath Binding. You should update the XPath on your XmlDataSource so that you just get a list of Countries, independent of Continent:
<XmlDataProvider x:Key="CountryStoreDataSource" XPath="/CountryStore/Continents/Countries">
<x:XData>
<CountryStore xmlns="">
<Continents Continent="Europe">
<Countries Country="Italy" Area="300"/>
<Countries Country="Iceland" Area="350"/>
</Continents>
<Continents Continent="Asia">
<Countries Country="China" Area="700"/>
<Countries Country="India" Area="650"/>
</Continents>
<Continents Continent="Africa">
<Countries Country="South Africa" Area="550"/>
<Countries Country="Egypt" Area="500"/>
</Continents>
</CountryStore>
</x:XData>
</XmlDataProvider>
Then, set the DataContext of the Grid:
<Grid DataContext="{StaticResource CountryStoreDataSource}" ../>
After that, both bindings of the ListBoxes can be updated to the following: ItemsSource="{Binding}"
.
Now, back to the question: show the average of the Areas. For this, you need to bind to the same list and apply a converter to do the calculation.
First, let's create the Converter, which simply parses the list and calculates the average with LINQ:
public class AreaConverter : MarkupExtension, IValueConverter
{
public override object ProvideValue(IServiceProvider serviceProvider)
{
return this;
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null) return 0;
//you can do this in one line, but I split it for clarity.
var xml = value as IEnumerable<XmlNode>;
var areas = xml.Select(x => x.Attributes["Area"].Value);
var avg = areas.Average(a => int.Parse(a));
return avg;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotSupportException();
}
}
After that, you can create the TextBlock to hold this value with this Binding:
<TextBlock Text="{Binding Converter={local:AreaConverter}}" />
Now the TextBlock should display the Average!
TIP: to test your given XPaths, you can use Notepad++ with the XML Tools plugin, which provides a Evaluate XPath Expression tool