[英]How to calculate the average from XMLDataProvider-data defined in XAML
I'm really new in WPF and I need your help. 我真的是WPF的新手,需要您的帮助。 I've app which allows user check continent and view containing countries.
我有允许用户检查大洲并查看包含国家的应用程序。 Country has two propetries: name and area.
国家有两个特点:名称和地区。 The problem is that I need to show average area of all continent's countries.
问题是我需要显示所有大洲国家的平均面积。 My data model is looks like this:
我的数据模型如下所示:
<XmlDataProvider x:Key="CountryStoreDataSource" XPath="CountryStore">
<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>
also I have templates to connect listboxes with my data model: 我也有模板来连接列表框和我的数据模型:
<Grid.Resources>
<DataTemplate x:Key="countryItemTemplate">
<Label Content="{Binding XPath=@Country}"/>
</DataTemplate>
<DataTemplate x:Key="areaItemTemplate">
<Label Content="{Binding XPath=@Area}"/>
</DataTemplate>
</Grid.Resources>
finally I have the implementations of my listboxes: 最后,我有了列表框的实现:
<ListBox
Grid.Row="1"
ItemsSource="{Binding XPath=Countries}"
ItemTemplate="{StaticResource countryItemTemplate}"
Margin="0,0,0,0" />
<ListBox
Grid.Row="1"
ItemsSource="{Binding XPath=Countries}"
ItemTemplate="{StaticResource areaItemTemplate}"
Margin="0,0,0,0"
Grid.Column="1"
Name="listBoxAreas"
/>
Actually I don't know how to get my values from listboxes in c# code and is there any way to get values and do something with them in xml? 实际上,我不知道如何从C#代码的列表框中获取值,并且有什么方法可以获取值并在xml中对它们执行某些操作? Thank you.
谢谢。
interesting question! 有趣的问题!
First of all, it seems like the XPaths you are using are not completely correct. 首先,似乎您使用的XPath并不完全正确。 If I understand you correctly, you want to display a ListBox with Countries, a ListBox with Areas and a TextBlock with
Avg(areas)
. 如果我对您的理解正确,则想显示一个带有国家的ListBox,一个带有Areas的ListBox和一个带有
Avg(areas)
的TextBlock。
First, let's simplify the XPath Binding. 首先,让我们简化XPath绑定。 You should update the XPath on your XmlDataSource so that you just get a list of Countries, independent of Continent:
您应该在XmlDataSource上更新XPath,以便仅获得独立于大陆的国家列表:
<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: 然后,设置网格的DataContext:
<Grid DataContext="{StaticResource CountryStoreDataSource}" ../>
After that, both bindings of the ListBoxes can be updated to the following: ItemsSource="{Binding}"
. 之后,可以将ListBoxes的两个绑定更新为以下内容:
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: 首先,让我们创建Converter,它简单地解析列表并使用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来使用此Binding来保存此值:
<TextBlock Text="{Binding Converter={local:AreaConverter}}" />
Now the TextBlock should display the Average! 现在,TextBlock应该显示平均值!
TIP : to test your given XPaths, you can use Notepad++ with the XML Tools plugin, which provides a Evaluate XPath Expression tool 提示 :要测试给定的XPath,可以将Notepad ++与XML Tools插件一起使用,该插件提供了一个Evaluate XPath Expression工具。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.