在选择列表框项目时查看对象属性值

时间:2018-12-17 04:46:45

标签: c#

我有一个基类Item和3个派生类:WeaponShieldArmor

我创建了一个列表框,并用所有三个派生类填充它。

我的问题是,在列表框中选择该类时,如何访问该类的属性值?我尝试过:

dynamic weapon = Convert.ChangeType(item, typeof(Weapon));

但是weapon不允许我访问属性值。我看到的智能感知选项与我看到的相同:

var item = LstStoreItems.SelectedItem;

我要实现的目标是从列表框中选择一个对象,然后根据所选对象填充一些标签。

示例

Weapon具有NameAttackTypeCostShield具有NameDefenseMaterialCost。每当我选择Weapon时,我都想在表单上填充标签以向用户显示此信息。当我选择Shield时,我想显示该信息。

4 个答案:

答案 0 :(得分:1)

if中带有方法重载的块在这里可能会有所帮助

private void SelectedItemChangedHandler()
{
    var item = LstStoreItems.SelectedItem;

    if (item is Weapon) SetLabelsFor(item as Weapon);
    else if (item is Shield) SetLabelsFor(item as Shield);
    else if (item is Armor) SetLabelsFor(item as Armor);
    else ClearLabels();
}

private void SetLabelsFor(Weapon weapon)
{
    label1.Text = weapon.Name;
    // etc.
}

private void SetLabelsFor(Shield shield)
{
    label1.Text = shield.Name;
    // etc.
}

private void SetLabelsFor(Armor armor)
{
    label1.Text = armor.Name;
    // etc.
}

答案 1 :(得分:0)

您可以使用类似的东西吗:

private void SelectOneItemBasedOnType(){
var selected=TheListBox.SelectedItem;
//Check for example, if the item is a shield.
if(selected is Shield){
Shield shield=(Shield) selected;
MessageBox.Show(shield.cost);
}
//Etc
}

答案 2 :(得分:0)

对于哪种最佳方法可能不满意,我不确定。我正在描绘“主从”类型的场景。尚不清楚不同的继承者有多“变异”,而遍历属性可能是一个挑战,这取决于它们在继承者之间的“差异”程度。

鉴于此,一种可行的解决方案是使Item成为抽象类,并创建一个抽象方法来“强制”继承者实现这一点。 Item的每个继承者都需要实现SetItemPropertiesLabels方法。有关其工作方式的示例……假设Panel的{​​{1}}旁边有一个ListBox。该面板包含描述当前所选Items的所有标签。列表框选择更改时,将清除面板上的当前标签,然后调用所选的Item Items方法。在面板上设置了SetPanelLabels属性的标签和文本。然后,调用“必需” Item方法以将所选项目添加为单独的属性。

使用这种方法,SetItemPropertiesLabels(panel)事件可能看起来像……

SelectedIndexChanged

物品类

private void listBox1_SelectedIndexChanged(object sender, EventArgs e) {
  Item selectedItem = (Item)listBox1.SelectedItem;
  ItemPanel.Controls.Clear();
  selectedItem.SetPanelLabels(ItemPanel);
}

装甲班

public abstract class Item {
  public string ItemName { get; set; }
  public string Cost { get; set; }

  public Item() {
    ItemName = "";
  }

  public Item(string itemName, string cost) {
    ItemName = itemName;
    Cost = cost;
  }

  public void SetPanelLabels(Panel panel) {
    Label lbl = new Label();
    lbl.AutoSize = true;
    lbl.Text = "Item Name: " + ItemName + "   Cost: " + Cost;
    lbl.Location = new System.Drawing.Point(10, 10);
    panel.Controls.Add(lbl);
    SetItemPropertiesLabels(panel);
  }

  // This is the method that all inheritors must implement.
  public abstract void SetItemPropertiesLabels(Panel panel);
}

Shield Class

class Armour : Item {
  public string Type { get; set; }
  public string Material { get; set; }

  public Armour() {
  }

  public Armour(string itemName, string cost) : base(itemName, cost) {
  }

  public override void SetItemPropertiesLabels(Panel panel) {
    Label lbl = new Label();
    lbl.AutoSize = true;
    lbl.Text = "Armour Type: " + Type + "  Material: " + Material;
    lbl.Location = new System.Drawing.Point(15, 50);
    panel.Controls.Add(lbl);
  }
}

武器课

class Shield : Item {
  public string Defense { get; set; }
  public string Material { get; set; }

  public Shield(string itemName, string cost) : base(itemName, cost) {
  }

  public override void SetItemPropertiesLabels(Panel panel) {
    Label lbl = new Label();
    lbl.AutoSize = true;
    lbl.Text = "Shield Defense: " + Defense + "  Material: " + Material;
    lbl.Location = new System.Drawing.Point(15, 50);
    panel.Controls.Add(lbl);
  }
}

希望这很有道理。

答案 3 :(得分:-1)

最终对我有用的是:

        if (!(LstPlayerItems.SelectedItem is Item item)) return;

        if (item.GetType() == typeof(Weapon) && item is Weapon weapon)
        {
            LblAttDef.Content = weapon.MinimumDamage + " to " + weapon.MaximumDamage;
            LblAttDefLabel.Content = "Attack";
        }

现在,这使我可以引用对象Weapon上的weapon属性,并完成我想要的工作。