我有一个基类Item
和3个派生类:Weapon
,Shield
,Armor
。
我创建了一个列表框,并用所有三个派生类填充它。
我的问题是,在列表框中选择该类时,如何访问该类的属性值?我尝试过:
dynamic weapon = Convert.ChangeType(item, typeof(Weapon));
但是weapon
不允许我访问属性值。我看到的智能感知选项与我看到的相同:
var item = LstStoreItems.SelectedItem;
我要实现的目标是从列表框中选择一个对象,然后根据所选对象填充一些标签。
示例
Weapon
具有Name
,Attack
,Type
和Cost
。 Shield
具有Name
,Defense
,Material
和Cost
。每当我选择Weapon
时,我都想在表单上填充标签以向用户显示此信息。当我选择Shield
时,我想显示该信息。
答案 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
属性,并完成我想要的工作。