Megatron
Megatron

Reputation: 2949

Using XML Attributes as list source in WPF

I need to be able to use a series of attributes as the source in a WPF list view. I'm currently stuck on how to do this. I know how to do it for XML nodes but not for attributes. Here's an example of what I'm trying to bind too:

<Stats HP="55000" MP="2500" SP="2500" Strength="212" Vitality="125" Magic="200" Spirit="162" Skill="111" Speed="109" Evasion="100" MgEvasion="100" Accuracy="100" Luck="55" />

I want each stat name/value to be an entry in the listview. Here's the code I've been trying to make work:

<TabControl.DataContext>
     <Binding ElementName="EnemyLevelsListBox" Path="SelectedItem"/>
</TabControl.DataContext>
<TabItem Header="Stats" Name="EnemyStatsTab">
      <ListView ItemsSource="{Binding XPath=Stats}" Height="310" Name="EnemyStatViewDisplay" Width="411" HorizontalAlignment="Left">
      <ListView.ItemTemplate>
            <DataTemplate>
                  <TextBlock Text="{Binding Path=Attribute.Name}" />
                  <TextBlock Text="{Binding Path=Attribute.Value}" />
            </DataTemplate>
       </ListView.ItemTemplate>
       </ListView>
</TabItem>

The TabControl.DataContext binding exposes the parent XMLNode of the Stats element. I know this for certain as I'm using subnodes of the parent elsewhere and they work correctly. I don't know what to put for the ListView ItemsSource or for the DataTemplate's textblock binds. Does someone know how to do this?

Upvotes: 0

Views: 1898

Answers (2)

Wallstreet Programmer
Wallstreet Programmer

Reputation: 9677

Why not just bind the listview to the attributes?

XAML:

<Window x:Class="WPF1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WPF1"
        Title="MainWindow" Height="350" Width="350">

    <StackPanel>
        <StackPanel.Resources>
            <local:AttributesToEnumerableConverter x:Key="AttributesToEnumerableConverter" />
        </StackPanel.Resources>
        <ListView ItemsSource="{Binding Path=Stats, Converter={StaticResource AttributesToEnumerableConverter}}">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="{Binding Path=Name}" Margin="5" />
                        <TextBlock Text="{Binding Path=Value}" Margin="5" />
                    </StackPanel>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackPanel>

</Window>

Code behind:

using System;
using System.Windows;
using System.Windows.Data;
using System.Xml.Linq;

namespace WPF1
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            DataContext = this;
        }

        public XElement Stats
        {
            get { return XElement.Parse("<Stats HP=\"55000\" MP=\"2500\" SP=\"2500\" Strength=\"212\" Vitality=\"125\" Magic=\"200\" Spirit=\"162\" Skill=\"111\" Speed=\"109\" Evasion=\"100\" MgEvasion=\"100\" Accuracy=\"100\" Luck=\"55\" />"); }
        }
    }

    public class AttributesToEnumerableConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return (value as XElement).Attributes(); 
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

Upvotes: 1

brunnerh
brunnerh

Reputation: 184526

You should not use XPath in the ItemsSource binding as you want to target the Attributes collection on the XmlNode object. You should make sure you are already having the Stats element as DataContext, then set the Path to Attributes:

<ListView ItemsSource="{Binding Attributes}" DataContext="<bind to stats element if necessary>">
    <ListView.View>
        <GridView>
            <GridViewColumn Header="Stat" DisplayMemberBinding="{Binding Name}"/>
            <GridViewColumn Header="Value" DisplayMemberBinding="{Binding Value}"/>
        </GridView>
    </ListView.View>
</ListView>

Upvotes: 1

Related Questions