0

是否可以调用基于文本值的方法?

如果可能,我不想使用“if”或“switch”语句。

如果是这样,我需要看什么才能做到这一点?

这只是为了尝试清理界面。

if 语句示例:

    if (cmb_Motor.SelectedItem.ToString() == "OutPortA")
             NXT_Brick.OutPortA.SetOutputState();
    else if (cmb_Motor.SelectedItem.ToString() == "OutPortB")
             NXT_Brick.OutPortB.SetOutputState();
    else if (cmb_Motor.SelectedItem.ToString() == "OutPortC")
             NXT_Brick.OutPortC.SetOutputState();

我想在“NXT_Brick”之后更改“OutPortA、B、C”。

4

5 回答 5

4

我能想到的最干净的方法是为您的组合框项目创建一个类,如下所示:

class Item
{
  public string Name{get;set;}
  public Action Action{get;set;}

  public override string ToString() { return Name; }
}

然后将此类的实例添加到组合框中:

cmbItems.Add(new Item{Name="Item1", Action=()=>{ /*action 1*/ });
cmbItems.Add(new Item{Name="Item2", Action=()=>{ /*action 2*/ });
cmbItems.Add(new Item{Name="Item3", Action=()=>{ /*action 3*/ });

并且在您选择的项目更改事件中(或在您的确定按钮按下,无论在哪里),您将您的SelectedItem属性转换为Item然后调用它的Action属性来运行代码。

((Item)cmbItems.SelectedItem).Action();
于 2012-08-02T20:15:26.457 回答
2

if并且switch语句可以隐藏在字典中,例如:

private IDictionary<string, OutPort> ports = new Dictionary<string, OutPort>{
  {"OutPortA", NXT_Brick.OutPortA},
  {"OutPortB", NXT_Brick.OutPortB},
  {"OutPortC", NXT_Brick.OutPortC}
}

用法:

if(ports.Contains(key))
{
 ports[key].SetOutputState();
}
于 2012-08-02T20:16:38.670 回答
1

组合框包含列表项。根据 MSDN,您可以将 ANYTHING 存储在组合框中,尽管它通常用于存储文本字符串。所以选择正确解决问题的最简单的解决方案。

public class FiringComboItem
{
   public string Text { get; set; }
   public Action OnClick { get; set; }
   override public ToString() { return Text; }
}

像这样将项目添加到组合中:

myCombo.Add ( new FiringComboItem 
    { 
        Text = "About", 
        OnClick = () => new AboutDialog.ShowDialog()
    });

在您的下拉处理程序中:

private void myCombo_OnSelectedIndexChanged(object sender, EventArgs e)
{
    (myCombo.SelectedItem As FiringComboItem).OnClick();
}
于 2012-08-02T20:35:34.100 回答
0

委托是指向函数/方法的指针,因此您可能想要使用它。例如,创建一个指向具有委托签名(参数及其类型)的方法的指针数组,并通过索引该数组来调用该方法。一个例子:

public delegate void SelectState();

public class Test
{
    SelectState[] stateMethods = new SelectState[]
    {
        new SelectState(SelectA),
        new SelectState(SelectC),
        new SelectState(SelectB),
        new SelectState(SelectB)
    };

    void SelectA() { /* ... */ }
    void SelectB() { /* ... */ }
    void SelectC() { /* ... */ }

    void DoSomething()
    {
        int index = cmb_Motor.SelectedIndex;
        // Get the method pointer.
        var method = stateMethods[index];
        // Call the method, one of the State*() methods.
        method();
    }
}

或者,如果您不想使用索引而是字符串,例如您的示例,您可能想要使用字典:

Dictionary<string, SelectState> stateMethods = new Dictionary<string, SelectState>
{
    {"OutPortA", new SelectState(SelectA)},
    {"OutPortB", new SelectState(SelectB)},
    {"OutPortC", new SelectState(SelectC)},
};
于 2012-08-02T20:15:18.583 回答
0

一个好的解决方案(一般来说 - 在您的特殊情况下可能不是最好的方法,但要判断这一点,我们需要更多信息)似乎将对象存储在 ComboBox 中,而不仅仅是字符串。这些对象应提供 ComboBox 中可见的文本以及运行您要调用的方法的方法。

在您的示例中,您似乎总是在调用实例的SetOutputState方法OutPort(假设此处的类名),因此您的 ComboBox 项目对象可能如下所示:

public class ComboItem
{
    public ComboItem(string displayName, OutPort outPort)
    {
        this.displayName = displayName;
        this.outPort = outPort;
    }

    private readonly string displayName;

    private readonly OutPort outPort;

    public override string ToString()
    {
        return displayName;
    }

    public OutPort OutPort {
        get {
            return outPort;
        }
    }
}

请注意,该ToString方法的结果将是 ComboBox 中用户可见的字符串。

您必须像这样填充 ComboBox:

cmb_Motor.Items.Add(new ComboItem("OutPortA", NXT_Brick.OutPortA);
cmb_Motor.Items.Add(new ComboItem("OutPortB", NXT_Brick.OutPortB);
cmb_Motor.Items.Add(new ComboItem("OutPortC", NXT_Brick.OutPortC);

然后,您可以像这样评估所选项目:

ComboItem selectedItem = cmb_Motor.SelectedItem as ComboItem;
if (selectedItem != null) {
    selectedItem.OutPort.SetOutputState();
}

如果您需要对所选项目执行的操作有更多变化,请将要执行的操作也移到ComboItem类中:

public class ComboItem
{
    public ComboItem(string displayName, OutPort outPort)
    {
        this.displayName = displayName;
        this.outPort = outPort;
    }

    private readonly string displayName;

    private readonly OutPort outPort;

    protected OutPort OutPort {
        get {
            return outPort;
        }
    }

    public override string ToString()
    {
        return displayName;
    }

    public virtual void DoWork()
    {
        outPort.SetOutputState();
    }
}

OutPort物业现在不再需要公开;您可以简单地调用DoWork所选项目。因此,评估代码可以更改为:

ComboItem selectedItem = cmb_Motor.SelectedItem as ComboItem;
if (selectedItem != null) {
    selectedItem.DoWork();
}

对于需要不同操作的任何事情,您现在可以派生一个新类,该类ComboItem会覆盖该DoWork方法以执行不同的操作。

于 2012-08-02T20:18:43.697 回答