WPF使用ItemsSource前必须清空Items集合,以及如何使用下拉框。

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

我的XAML如下所示:

http://puu.sh/aLLrx.png

http://puu.sh/aLLsQ.jpg

我的代码是:

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

}

字符类(以防万一): http://pastebin.com/GFycKqDC

物品类(以防万一): http://pastebin.com/RgXzbFHk

这是一个关于RPG的项目,您需要使用数据绑定来创建一个ObservableCollection,用于ComboBox,并查看每个角色。

我遇到的问题是: 在我的ComboBox中,我想能够显示带有“图像”的角色,旁边是他们的“等级”和“名称”

但我不希望它是静态的,我想创建一个角色列表,并将ItemsSource绑定到我的ComboBox,以便无论选择哪个角色,基于该角色的信息都会更新。 我该怎么做?

有人告诉我要创建一个角色列表,然后创建一个数据模板用于ComboBox Item,其中包含绑定到selectedItem的图片、名称和等级(我称之为charList),但无论我是在代码中还是在XAML中进行,它都会抛出一个异常,说在绑定之前集合必须为空。

我希望将数据模板中的属性绑定到selectedItem,以便标签和信息能够适当更新。
我做错了什么,为什么会抛出这个异常?
编辑:
好的,现在问题已经解决!但是,为什么我的Label绑定对Character.Name和Character.Level仍然不起作用?

http://puu.sh/aLPr7.jpg

编辑2 public MainWindow() { InitializeComponent(); Character.Add(new Character("巴基勇士")); Character.Add(new Character("蓝色骑士")); 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; }
    }

然后是 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>

每个ComboBoxItem都有一个Character实例作为它的DataContext,因此正确的路径是Name和Level。它正在寻找一个名为Character的属性,该属性本身具有一个名为Name的属性。不确定为什么您有一个List<Character>和一个ObservableCollection<Character>。 - Lee O.
如果这解决了问题,请标记我的答案。 - Lee O.
我能用“Character”做与“charList”相同的事情吗?它会以同样的方式工作吗? - Technocrat
通常情况下,当你需要绑定到一个集合作为 ItemsSource 时,你会使用 ObservableCollection 作为类型,因为它可以在你添加/删除集合中的元素时通知绑定,而 List 则不会。 - Lee O.
为什么我的新代码会抛出异常?TargetInvocationException未处理 @LeeO。 - Technocrat
创建一个新问题,只包括发生异常的代码部分。 - Lee O.
1个回答

22
你定义了两次ItemsSource。 一次使用:
ItemsSource="{Binding charList}"
<ComboBoxItem>

您需要将ComboBoxItem元素替换为ComboBox.ItemTemplate,并为您的ComboxItem创建一个DataTemplate。然后,您需要将Image Source绑定到角色类上的属性,或者使用ItemTemplateSelector使其使用适当的DataTemplate项。

如果只更改图像源位置,还可以使用一个数据触发器绑定到定义字符类的属性。


<ComboBoxItem>没有ItemsSource,只有一个绑定路径到标签内容的Binding Path?这算是重复定义吗?哦,我明白了,如果我把它去掉,它现在会显示对象位置“ItemControl.Character”,而不是字符。我应该如何编辑它以达到我想要的效果? - Technocrat
你正在使用该代码向ComboBox添加另一个ComboBoxItem。就像<TextBox>将显示的文本应用于TextBox一样。<ComboBox><ComboBoxItem .....></ComboBox>将把该ComboBoxItem添加到ItemsSource中。 - Lee O.
你真正想做的是定义用于ComboBoxItems的模板。除非你将Character作为基类,然后将不同的角色类型作为子类,否则你将不得不使用ItemTemplateSelector来允许不同的模板。然后,你可以根据它们的数据类型为不同的项创建DataTemplates。 - Lee O.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接