Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF Items collection must be empty before using ItemsSource and help using Combo Box

Tags:

c#

combobox

wpf

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="1.5*"/>
        <ColumnDefinition/>
    </Grid.ColumnDefinitions>  



    <Grid Grid.Column="0" Background="DarkCyan">
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>    
            <ComboBox ItemsSource="{Binding Path=charList}" x:Name="comboBox" VerticalAlignment="Top" Width="Auto" Grid.ColumnSpan="2">
            <ComboBoxItem>
                <StackPanel Orientation="Horizontal">
                    <Image Source="Pictures\bagi_warrior.jpg" Width="100" Height="150"/>
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition/>
                            <RowDefinition Height="6*"/>
                        </Grid.RowDefinitions>
                        <Label Grid.Row="0" Content="{Binding Path=Character.Name}" FontSize="30"/>
                        <Label Grid.Row="1" Content="{Binding Path=Character.Level}" FontSize="20"/>
                    </Grid>
                </StackPanel>
            </ComboBoxItem>
            <ComboBoxItem>
                <StackPanel Orientation="Horizontal">
                    <Image Source="Pictures\azure_knight.jpg" Width="100" Height="130"/>
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition/>
                            <RowDefinition Height="6*"/>
                        </Grid.RowDefinitions>
                        <Label Grid.Row="0" Content="Azure Knight"  FontSize="30"/>
                        <Label Grid.Row="1" Content="Level 158"  FontSize="20"/>
                    </Grid>
                </StackPanel>
            </ComboBoxItem>
        </ComboBox>
        <Label x:Name="strLabel" Grid.Column="0" VerticalAlignment="Bottom" Height="30" Content="Str: " HorizontalContentAlignment="Center" FontSize="16"/>
        <Label x:Name="intLabel" Grid.Column="1" VerticalAlignment="Bottom" Height="30" Content="Int: " HorizontalContentAlignment="Center" FontSize="16"/>
        <Label x:Name="dexLabel" Grid.Column="0" Grid.Row="1" VerticalAlignment="Center" Height="30" Content="Dex: " HorizontalContentAlignment="Center" FontSize="16"/>
        <Label x:Name="goldLabel" Grid.Column="1" Grid.Row="1" VerticalAlignment="Center" Height="30" Content="Gold: " HorizontalContentAlignment="Center" FontSize="16"/>


    </Grid>
    <Grid Grid.Column="1">
        <Grid.RowDefinitions>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <DataGrid x:Name="MyGrid" ItemsSource="{Binding Path=Item}"></DataGrid>
    </Grid>
</Grid>

My XAML is such, it looks like this:

http://puu.sh/aLLrx.png

http://puu.sh/aLLsQ.jpg

my code is:

 public partial class MainWindow : Window
 {

    Character aloken;
    Character azureKnight;
    Character bagiWarrior;
    Character incarMagician;
    Character segitaHunter;
    Character segnale;
    Character viciousSummoner;
    private List<Character> _charList = new List<Character>();

    public MainWindow()
    {
        InitializeComponent();
        charList.Add(new Character("Bagi Warrior"));
        this.Item = new ObservableCollection<Item>();
        this.Character = new ObservableCollection<Character>();

        this.DataContext = this;
        //Character.Add(new Character(name: "Bagi Warrior", level: 197, characterClass: CharacterClass.Bagi_Warrior, gender: Gender.Male, strength: 450, intelligence: 4, dexterity: 84, gold: 147203352));
        //Character.Add(new Character(name: "Azure Knight", level: 158, characterClass: CharacterClass.Azure_Knight, gender: Gender.Male, strength: 390, intelligence: 120, dexterity: 92, gold: 204220567));
        //Character.Add(new Character(name: "Incar Magician", level: 169, characterClass: CharacterClass.Incar_Magician, gender: Gender.Female, strength: 4, intelligence: 512, dexterity: 57, gold: 172223520));
        //Character.Add(new Character(name: "Vicious Summoner", level: 203, characterClass: CharacterClass.Vicious_Summoner, gender: Gender.Male, strength: 423, intelligence: 89, dexterity: 45, gold: 114225587));

    }

    public List<Character> charList
    {
        get { return _charList; }
        set { _charList = value; }
    }


    private ObservableCollection<Character> _Character;

    public ObservableCollection<Character> Character
    {
        get { return _Character; }
        set { _Character = value; }
    }


    private ObservableCollection<Item> _Item;
    public ObservableCollection<Item> Item
    {
        get { return _Item; }
        set { _Item = value; }
    }

}

Character Class (just in case): http://pastebin.com/GFycKqDC

Item Class (just in case): http://pastebin.com/RgXzbFHk

It's a project on a RPG where you have to use databinding for a combobox and to create an ObservableCollection for the combobox and view each Character.

The issue i'm running into is: In my combobox, I want to be able to display the Character with their 'image' and next to it, their 'level' and 'name'

But I don't want it to be static, I want to create a list of Characters and bind the ItemsSource to my ComboBox so that no matter which character I select, information based on that character will update. How do I do this?

I was told that creating a List of Characters, then make a data template for ComboBox Item that holds a pic, name, and level that are bound to selectedItem would do the job (which I did called charList) but whether I do it in code, or in XAML, it throws an exception saying that the collection must be empty before I bind to it.

I want to bind the properties in the datatemplate to selectedItem so that the labels and information will update appropriately.

What am I doing wrong, and why is this exception being thrown?

EDIT

Okay so now the problem is fixed! However, why does my Label binding still not work for Character.Name and Character.Level?

http://puu.sh/aLPr7.jpg

EDIT 2 public MainWindow() { InitializeComponent(); Character.Add(new Character("Bagi Warrior")); Character.Add(new Character("Azure Knight")); this.Item = new ObservableCollection(); this.Character = new ObservableCollection();

        this.DataContext = this;
        //Character.Add(new Character(name: "Bagi Warrior", level: 197, characterClass: CharacterClass.Bagi_Warrior, gender: Gender.Male, strength: 450, intelligence: 4, dexterity: 84, gold: 147203352));
        //Character.Add(new Character(name: "Azure Knight", level: 158, characterClass: CharacterClass.Azure_Knight, gender: Gender.Male, strength: 390, intelligence: 120, dexterity: 92, gold: 204220567));
        //Character.Add(new Character(name: "Incar Magician", level: 169, characterClass: CharacterClass.Incar_Magician, gender: Gender.Female, strength: 4, intelligence: 512, dexterity: 57, gold: 172223520));
        //Character.Add(new Character(name: "Vicious Summoner", level: 203, characterClass: CharacterClass.Vicious_Summoner, gender: Gender.Male, strength: 423, intelligence: 89, dexterity: 45, gold: 114225587));

    }

    //public List<Character> charList
    //{
    //    get { return _charList; }
    //    set { _charList = value; }
    //}


    private ObservableCollection<Character> _Character;

    public ObservableCollection<Character> Character
    {
        get { return _Character; }
        set { _Character = value; }
    }

and then XAML:

<Grid Grid.Column="0" Background="DarkCyan">
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <ComboBox ItemsSource="{Binding Path=Character}" x:Name="comboBox" VerticalAlignment="Top" Width="Auto" Grid.ColumnSpan="2">
            <ComboBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <Image x:Name="image" Source="{Binding Source={StaticResource ImageConverter}}" Width="100" Height="150"/>
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition/>
                                <RowDefinition Height="6*"/>
                            </Grid.RowDefinitions>
                            <Label Grid.Row="0" Content="{Binding Path=Character.Name}" FontSize="30"/>
                            <Label Grid.Row="1" Content="{Binding Path=Character.Level}" FontSize="20"/>
                        </Grid>
                    </StackPanel>
                </DataTemplate>
            </ComboBox.ItemTemplate>
like image 840
Technocrat Avatar asked Aug 09 '14 23:08

Technocrat


1 Answers

You are defining the ItemsSource twice.

Once using

ItemsSource="{Binding charList}"

and then again with

<ComboBoxItem>

You will want to replace the ComboBoxItem element with ComboBox.ItemTemplate and create a DataTemplate for your ComboxItem. Then you'll want to either bind the Image Source to a property on the Character class or use a ItemTemplateSelector to have it use the appropriate DataTemplate for the item. If only the image source location is changing, you could also use a datatrigger bound to the property defining the character class.

like image 114
Lee O. Avatar answered Oct 07 '22 07:10

Lee O.