Search code examples
c#wpfbindingwpfdatagrid

WPF C# Binding label to DataGrid containing ObervableCollection of custom objects


Ok, so here's my problem. I'm creating a simple application for my RPG system. It's a character chart for players who can create their heroes and view statistics. So, here's the important things from base class for a Hero:

namespace CharacterChart.Classes
{
[DataContract(Name = "Character", Namespace = "http://www.jambs.com")]
abstract class Base : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    [DataMember]
    private string Name;

    [DataMember]
    public ObservableCollection<Attribute> Attributes;

    protected void OnPropertyChanged(string info)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(info));
        }
    }
    public Base()
    {
        this.Name = "Nowa postać";
        Attributes = new ObservableCollection<Attribute>();
        Attributes.Add(new Attribute { Key = 'S', Value = 0 });
        Attributes.Add(new Attribute { Key = 'Z', Value = 0 });
        Attributes.Add(new Attribute { Key = 'P', Value = 0 });
        Attributes.Add(new Attribute { Key = 'B', Value = 0 });
        Attributes.Add(new Attribute { Key = 'C', Value = 0 });
        Attributes.Add(new Attribute { Key = 'I', Value = 0 });
        Attributes.Add(new Attribute { Key = 'W', Value = 0 });
        Attributes.Add(new Attribute { Key = 'D', Value = 0 });
    }

    public string name
    {
        get { return Name; }
        set { Name = value; OnPropertyChanged("Name"); }
    }

    public ObservableCollection<Attribute> attributes
    {
        get { return Attributes; }
        set { Attributes = value; OnPropertyChanged("Attributes"); }
    }
}
}

Here's the code for Attribute class (I wanted to use a Dictionary, but it didn't contain OnPropertyChanged):

 class Attribute : INotifyPropertyChanged
 {
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string info)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(info));
        }
    }

    [DataMember]
    private char key;

    [DataMember]
    private byte number;

    public char Key
    {
        get { return key; }
        set { key = value; OnPropertyChanged("Key"); }

    }
    public byte Value
    {
        get { return number; }
        set { number = value; OnPropertyChanged("Value"); }
    }
}

In the main program I'm declaring an ObservableCollection of heroes and set an ItemsSource for Datagrid. In XAML it's something like that:

<DataGrid Name="DataHeroes" Grid.Column="0" AutoGenerateColumns="False">
        <DataGrid.Columns>
            <DataGridTextColumn Header="Name" Binding="{Binding Path=name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
            <DataGridTextColumn Header="Strength" Binding="{Binding Path=attributes[0].Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
        </DataGrid.Columns>
    </DataGrid>

Now I want to add a functionality, that will let me select a Hero in DataGrid and then displaying all of his stats. Unfortunately, displaying an Attribute doesn't work for me. Here's what I tried:

<TextBlock Text="{Binding ElementName=DataHeroes, Path=SelectedIndex.attributes[0].Value, Mode=OneWay}" Grid.Column="2"/>

Any ideas how should I refer to my Collection of Attributes and displaying selected one?

This example refers only to a single attribute, I'll expand them later.


Solution

  • SelectedIndex returns an integer, which obviously doesn't have a "attributes" property. Change your line to:

    <TextBlock Text="{Binding ElementName=DataHeroes, Path=SelectedItem.attributes[0].Value, Mode=OneWay}" Grid.Column="2"/>
    

    SelectedItem returns the bound object that is selected on the UI. (MSDN)

    Note that this returns the first user selected item if multiple items are selected.