从字符串名称调用方法

时间:2017-06-27 01:07:02

标签: c# winforms mouseevent

我正在使用c#,我有一个实例化很多PictureBox按钮的项目。我还编写了所有click,hover,mouseUp,mouseDown事件方法。如何从字符串名称调用方法,以便我不必手动编写所有这些方法?提前谢谢,卡森

Dictionary<string, PictureBox> buttonList = new Dictionary<string,PictureBox>();
string buttonName = "button_file";

buttonList[buttonName].Click += new EventHandler(buttonName + "_click");

public void button_file_click(object sender, EventArgs e)
{
     // do on click stuff here
}

4 个答案:

答案 0 :(得分:2)

如果设置按钮的Name属性,则可以这样:

buttonList[buttonName].Name = buttonName;
buttonList[buttonName].Click += ButtonClick;

并且只有一个元数据所有按钮点击,但按照他们的名字:

public void ButtonClick(object sender, EventArgs e)
{
    var btn = (Button)sender;
    btn.Text = btn.Name;  //only for demo
}

但你可以完全编写自己的方法:

buttonList[buttonName].Click += (s,e)=> clickEvent(buttonList[buttonName], buttonName);

这是一个简短的lambda函数,它接受Click事件单一的相应参数并激活你的自定义函数clickEvent

public void clickEvent(Button thePressedButton, string nameOfPresedButton)
{
    thePressedButton.Text = btn.nameOfPresedButton; //only for demo
}

答案 1 :(得分:0)

从您的示例代码中,我假设您希望所有人都拨打<style> .s4-wpcell-plain{ text-align: -webkit-center; } </style> <table style="width:100%" cellpadding="0" cellspacing="0"> <tbody> <tr> <td id="MSOZoneCell_WebPartWPQ2" valign="top" class="s4-wpcell-plain"> <!-- content --> </td> </tr> </tbody> </table>

在这种情况下,只需将eventhandler设置为该方法:

button_file_click

答案 2 :(得分:0)

方法名称还不够......你还需要一个类名...但假设该方法属于当前类(this),你可以使用Reflection来做到这一点: / p>

public void ExecuteMethod(string methodName)
{
    var methodInfo = this.GetType().GetMethod(methodName);
    methodInfo.Invoke(this, new [] {});
}

但您不能将上述内容分配给某个事件,因为它不是正确的代理类型;大多数事件处理程序需要senderEventArgs。因此,为了使您的代码更有效,您需要更多的粘合剂:

Dictionary<string, PictureBox> buttonList = new Dictionary<string,PictureBox>();
string buttonName = "button_file";

buttonList[buttonName].Click += GetHandler(buttonName + "_click");

public Action<object, EventArgs> GetHandler(string handlerName)
{
    var methodInfo = this.GetType().GetMethod(handlerName, new Type[] {typeof(object), typeof(EventArgs)});
    return new Action<object, EventArgs> (sender, eventArgs) => methodInfo.Invoke(this, new [] {sender, eventArgs});
}

这里的想法是GetHandler返回带有正确签名的Action(按顺序接受一个对象和一个EventArgs),写成Action<object, EventArgs>GetHandler方法使用反射在当前类中查找正确的方法,然后创建一个lambda表达式,通过反射调用该方法,将参数作为数组传递。

上面当然只是一个例子......将代理存储在第一次加载页面时计算的静态字典中可能会更好。

话虽如此,如果您正在寻找基于运行时参数的事件处理灵活性,更好的方法可能是使用Command event,这允许您将字符串传递给处理程序,然后可以根据字符串的内容采取不同的操作。这样你就可以对处理程序引用进行硬编码,但仍然会软编码它将做什么。

Dictionary<string, PictureBox> buttonList = new Dictionary<string,PictureBox>();
string buttonName = "button_file";

buttonList[buttonName].Command += buttonList_Command;
buttonList[buttonName].CommandName = buttonName;

protected void buttonList_Command(object sender, CommandEventArgs e)
{
     switch (e.CommandName)
     {
          case buttonName:
              //Do stuff for button_file
              break;
          case "Foo":
              //Do stuff for some other button named foo
              break;
          default:
              throw new InvalidOperationException();
     }
 }

答案 3 :(得分:0)

您可以使用反射按名称查找类的方法,然后使用该方法创建事件处理程序委托。例如:

 void bindHandler(string buttonName)
        {
            string methodName = buttonName + "_click";  
            System.Reflection.MethodInfo m = this.GetType().GetMethods().FirstOrDefault(x => x.Name == buttonName + "_click");
            PictureBox button = buttonList[buttonName];
            Delegate handler = Delegate.CreateDelegate(typeof(EventHandler), this, m);
            button.Click += (EventHandler)handler;
        }

填写工作代码:

namespace WindowsFormsApp1Cs
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            MyClass c = new MyClass();
            foreach (var item in c.buttonList)
            {
                this.Controls.Add(item.Value);
            }
        }
    }
    public class MyClass
    {
        public Dictionary<string, PictureBox> buttonList;
        public delegate void MyClickHandler(object sender, EventArgs e);
        public MyClass()
        {
            buttonList = new Dictionary<string, PictureBox>();
            buttonList.Add("button_file_1", new PictureBox() { Width = 100, Height = 100, Name = "button_file_1", Anchor = AnchorStyles.Top | AnchorStyles.Left, Top = (buttonList.Count * 100) + 10, Left = 10, ImageLocation="0.jpg" });
            buttonList.Add("button_file_2", new PictureBox() { Width = 100, Height = 100, Name = "button_file_2", Anchor = AnchorStyles.Top | AnchorStyles.Left, Top = (buttonList.Count * 100) + 10, Left = 10, ImageLocation = "0.jpg" });
            buttonList.Add("button_file_3", new PictureBox() { Width = 100, Height = 100, Name = "button_file_3", Anchor = AnchorStyles.Top | AnchorStyles.Left, Top = (buttonList.Count * 100) + 10, Left = 10, ImageLocation = "0.jpg" });
            foreach (var item in buttonList)
            {
                bindHandler(item.Key);
            }
        }
        void bindHandler(string buttonName)
        {
            string methodName = buttonName + "_click";  
            System.Reflection.MethodInfo m = this.GetType().GetMethods().FirstOrDefault(x => x.Name == buttonName + "_click");
            PictureBox button = buttonList[buttonName];
            Delegate handler = Delegate.CreateDelegate(typeof(EventHandler), this, m);
            button.Click += (EventHandler)handler;
        }
        public void button_file_1_click(object sender, EventArgs e)
        {
            Debug.WriteLine("button_file_1_click");
        }
        public void button_file_2_click(object sender, EventArgs e)
        {
            Debug.WriteLine("button_file_2_click");
        }
        public void button_file_3_click(object sender, EventArgs e)
        {
            Debug.WriteLine("button_file_3_click");
        }
    }
}