C# 如何从XAML中定义的XMLDataProvider数据计算平均值

C# 如何从XAML中定义的XMLDataProvider数据计算平均值,c#,xaml,data-binding,xpath,xmldatasource,C#,Xaml,Data Binding,Xpath,Xmldatasource,我是WPF的新手,需要你的帮助。 我有一个应用程序,允许用户检查大陆和查看包含国家。国家有两个属性:名称和面积。问题是我需要显示所有大陆国家的平均面积。 我的数据模型如下所示: <XmlDataProvider x:Key="CountryStoreDataSource" XPath="CountryStore"> <x:XData> <CountryStore xmlns="">

我是WPF的新手,需要你的帮助。 我有一个应用程序,允许用户检查大陆和查看包含国家。国家有两个属性:名称和面积。问题是我需要显示所有大陆国家的平均面积。 我的数据模型如下所示:

       <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>

此外,我还有模板将列表框与我的数据模型连接起来:

        <Grid.Resources>
            <DataTemplate x:Key="countryItemTemplate">
                <Label Content="{Binding XPath=@Country}"/>
            </DataTemplate>
            <DataTemplate x:Key="areaItemTemplate">
                <Label Content="{Binding XPath=@Area}"/>
            </DataTemplate>
        </Grid.Resources>

最后,我有我的列表框的实现:

           <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"
                />

实际上,我不知道如何从c#代码中的列表框中获取值,是否有任何方法可以获取值并在xml中处理它们?谢谢。

有趣的问题

首先,您使用的XPath似乎不完全正确。如果我理解正确,您希望显示带有国家/地区的列表框、带有区域的列表框和带有
Avg(Areas)
的文本块

首先,让我们简化XPath绑定。您应该在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>
之后,您可以创建TextBlock以使用此绑定保存此值:

 <TextBlock Text="{Binding Converter={local:AreaConverter}}" />

现在文本块应该显示平均值


提示:要测试给定的XPath,您可以使用Notepad++和XML工具插件,该插件提供了一个评估XPath表达式工具

非常感谢,如何在XML文件中正确添加AreaConverter类?它无法识别{local:AreaConverter}您必须在xaml的根目录中定义名称空间:
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();
    }
}
 <TextBlock Text="{Binding Converter={local:AreaConverter}}" />