user2453973
user2453973

Reputation: 309

Binding ComboBox SelectedItem to Datagrid

Having some problems displaying strings in a datagrid.

To explain the code: I am binding a collection of Soldiers to a ComboBox. A Soldier has its own collection of weapons.

When I select a specific soldier in the ComboBox, I want that soldier's weapons displayed in the datagrid. I believe I'm binding correctly, but the datagrid always comes up blank. Anybody know what i'm doing wrong?

XAML

<Grid>
    <ComboBox x:Name="Character_ComboBox" HorizontalAlignment="Left" VerticalAlignment="Top" Width="328" Height="25">
    </ComboBox>
</Grid>

<DataGrid x:Name="Character_items_datagrid" ItemsSource="{Binding ElementName=Character_ComboBox, Path= SelectedItem.Equipment, Mode=OneWay}" Margin="328,0,0,0" Grid.RowSpan="2" >
    <DataGrid.Columns>
        <DataGridTextColumn Header="Primary"  Binding="{Binding Primary, Mode=TwoWay}" FontWeight="Bold" Foreground="Black" Width="0.1*"></DataGridTextColumn>
        <DataGridTextColumn Header ="Secondary" Binding="{Binding Secondary, Mode=TwoWay}" Width="0.1*"></DataGridTextColumn>
    </DataGrid.Columns>
</DataGrid>

Soldier Class

public class Soldier 
{
    public string Soldier_Class { get; set; }
    public ObservableCollection<Weapons> Equipment { get; set; }
}

Weapons Class

public class Weapons
{
    string Primary { get; set; }
    string Secondary { get; set; }

    public Weapons(string primary, string secondary)
    {
        this.Primary = primary;
        this.Secondary = secondary;
    }
}

MainWindow

public ObservableCollection<Soldier> squad_members = new ObservableCollection<Soldier>();

public MainWindow()
{
    InitializeComponent();

    squad_members.Add(new Soldier() { Soldier_Class = "Assult Soldier", Equipment = new ObservableCollection<Weapons>() { new Weapons("M4 Rifle", "Compact 45 Pistol")}});
    squad_members.Add(new Soldier() { Soldier_Class = "SMG Soldier", Equipment = new ObservableCollection<Weapons>() { new Weapons("RPK Machine Gun", "HK Shotgun"), new Weapons("SAW Machine Gun", "Compact 45 Pistol")}});
    squad_members.Add(new Soldier() { Soldier_Class = "Juggernaut", Equipment = new ObservableCollection<Weapons>() { new Weapons("MP5", "Bowie Knife") }});

    Binding comboBinding = new Binding();
    comboBinding.Source = squad_members;

    BindingOperations.SetBinding(Character_ComboBox, ComboBox.ItemsSourceProperty, comboBinding);
    Character_ComboBox.DisplayMemberPath = "Soldier_Class";
    Character_ComboBox.SelectedValuePath = "Soldier_Class";
}

Result:

enter image description here

Upvotes: 1

Views: 1539

Answers (2)

Mike Fuchs
Mike Fuchs

Reputation: 12319

Your primary problem is the public access modifier, as har07 wrote.

There are a lot of other things you can improve as well. Implement INotifyPropertyChanged for your classes, so any change to the properties is immediately reflected by the UI. Without compelling reasons, do not create bindings in code. Use a ViewModel to bind to, instead of binding directly to elements like ComboBox.SelectedItem. Set AutoGenerateColumns to false if you want to style your columns (your code would produce four columns). Use Grid.ColumnDefinitions instead of assigning a fixed margin.

Models:

using System.Collections.ObjectModel;
using System.ComponentModel;

namespace WpfApplication1.ViewModels
{
    public class SquadViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        private ObservableCollection<Soldier> _squadMembers;
        public ObservableCollection<Soldier> SquadMembers { get { return _squadMembers; } set { _squadMembers = value; OnPropertyChanged("SquadMembers"); } }

        private Soldier _selectedSoldier;
        public Soldier SelectedSoldier { get { return _selectedSoldier; } set { _selectedSoldier = value; OnPropertyChanged("SelectedSoldier"); } }


        public SquadViewModel()
        {
            SquadMembers = new ObservableCollection<Soldier>()
            {
                new Soldier() { SoldierClass = "Assult Soldier", Equipment = new ObservableCollection<Weapon>() { new Weapon("M4 Rifle", "Compact 45 Pistol") } },
                new Soldier() { SoldierClass = "SMG Soldier", Equipment = new ObservableCollection<Weapon>() { new Weapon("RPK Machine Gun", "HK Shotgun"), new Weapon("SAW Machine Gun", "Compact 45 Pistol") } },
                new Soldier() { SoldierClass = "Juggernaut", Equipment = new ObservableCollection<Weapon>() { new Weapon("MP5", "Bowie Knife") } }
            };
        }
    }

    public class Soldier : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        private string _soldierClass;
        public string SoldierClass { get { return _soldierClass; } set { _soldierClass = value; OnPropertyChanged("SoldierClass"); } }

        private ObservableCollection<Weapon> _equipment;
        public ObservableCollection<Weapon> Equipment { get { return _equipment; } set { _equipment = value; OnPropertyChanged("Equipment"); } }
    }

    public class Weapon : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        private string _primary;
        string Primary { get { return _primary; } set { _primary = value; OnPropertyChanged("Primary"); } }

        private string _secondary;
        string Secondary { get { return _secondary; } set { _secondary = value; OnPropertyChanged("Secondary"); } }

        public Weapon(string primary, string secondary)
        {
            this.Primary = primary;
            this.Secondary = secondary;
        }
    }
}

Xaml:

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

    <Window.DataContext>
        <vm:SquadViewModel />
    </Window.DataContext>

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <ComboBox x:Name="CbxCharacter" HorizontalAlignment="Left" VerticalAlignment="Top" Width="328" Height="25"
                  ItemsSource="{Binding SquadMembers}" SelectedItem="{Binding SelectedSoldier}"
                  DisplayMemberPath="SoldierClass" SelectedValuePath="SoldierClass"/>

        <DataGrid x:Name="DgCharacterItems" ItemsSource="{Binding SelectedSoldier.Equipment, Mode=OneWay}" Grid.Column="1" AutoGenerateColumns="False"  >
            <DataGrid.Columns>
                <DataGridTextColumn Header="Primary" Binding="{Binding Primary, Mode=TwoWay}" FontWeight="Bold" Foreground="Black" Width="*" />
                <DataGridTextColumn Header="Secondary" Binding="{Binding Secondary, Mode=TwoWay}" Width="*" />
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

Upvotes: 0

har07
har07

Reputation: 89285

You need to make properties in the model public for binding to be able to work :

public class Weapons
{
    public string Primary { get; set; }
    public string Secondary { get; set; }
    .....
}

Your DataGrid looks populated with items correctly, just the properties of each item are not correctly displayed in the columns. This is indication that binding engine can't access the item's properties due to it's private accessibility.

Upvotes: 1

Related Questions