【问题标题】:C# using an int value after triggering an eventC# 在触发事件后使用 int 值
【发布时间】:2011-08-15 12:06:30
【问题描述】:

我一次又一次地遇到同样的问题。我需要在按钮事件、双击或任何事情之后使用用户输入的值。当我与设计器一起做时,它会自动将 txt 控件及其值传递给整个程序,我可以在任何地方使用它。但以编程方式我无法解决它。 这是一个小例子:

        private void Form1_Load(object sender, EventArgs e)
    {
        string blabla = "anything";

        Button btn = new Button();
        btn.Location = new Point(10, 40);
        btn.Text = "Click me";
        btn.Click += new EventHandler(btn_Click);
        this.Controls.Add(btn);

    }
    void btn_Click(object sender, EventArgs e)
    {
        MessageBox.Show(blabla);
    }

这不起作用,所以我添加了一个“公共”并且脚本如下:

    public string blabla;
    private void Form1_Load(object sender, EventArgs e)
    {
        blabla = "anything";

        Button btn = new Button();
        btn.Location = new Point(10, 40);
        btn.Text = "Click me";
        btn.Click += new EventHandler(btn_Click);
        this.Controls.Add(btn);

    }
    void btn_Click(object sender, EventArgs e)
    {
        MessageBox.Show(blabla);
    }

因此我可以将变量与更改后的值一起使用。这也适用于控件。 这可行,但这会在更大的应用程序中产生数千个公共变量。如何通过失去这些公众来提高可读性?有没有办法使用“参考”?我在自动“提取方法”上看到了它,我只是不知道,如何将它与事件一起使用。

也许我在这方面走错了路,如果有捷径或其他解决方案,请帮助。

【问题讨论】:

    标签: c# events controls


    【解决方案1】:

    两个 sn-ps 之间的重要变化不是您将变量公开 - 而是您将其从 Form1_Load 方法中的 local 变量更改为 实例变量。如果您在同一个类中处理它,它仍然可以是私有实例变量。

    但是,另一种选择是将其保留为局部变量,但使用匿名函数来处理事件:

    private void Form1_Load(object sender, EventArgs e)
    {
        string blabla = "anything";
    
        Button btn = new Button();
        btn.Location = new Point(10, 40);
        btn.Text = "Click me";
        btn.Click += (sender, args) => {
            MessageBox.Show(blabla);
            // Other code here, but hopefully not too much...
        };
        this.Controls.Add(btn);
    }
    

    (如前所述,为了可读性,您不想让匿名函数太大 - 但它总是可以调用具有所有适当状态的 另一个 方法。)

    编辑:当您使用 VS2005 时,您只使用 C# 2,因此您不能使用 lambda 表达式。不过,您可以使用匿名方法。代码将是:

    private void Form1_Load(object sender, EventArgs e)
    {
        string blabla = "anything";
    
        Button btn = new Button();
        btn.Location = new Point(10, 40);
        btn.Text = "Click me";
        btn.Click += delegate {
            MessageBox.Show(blabla);
            // Other code here, but hopefully not too much...
        };
        this.Controls.Add(btn);
    }
    

    【讨论】:

    • 他真的应该将按钮创建为表单加载中的局部变量吗?这不是回修吗?
    • @Jethro:为什么不呢?如果除了处理事件之外没有什么需要访问控件,我不明白为什么会出现问题。
    • 确实有道理。谢谢。
    • Jethro,你能解释一下吗?我有大量的控件,我需要根据相关的数据库表、事件、选择等以编程方式添加它们,如果我能让它更具可读性,那就太好了。
    • 抱歉,我的 VS 已将 btn.Click +=(sender,e) => { MessageBox.Show(blabla);} 标记为错误。
    【解决方案2】:

    所有 winforms 控件都倾向于具有 Tag 属性,类型为 object,如果您愿意,您可以使用它来存储您自己的自定义数据。它不是特别好的做法,并显示了一些其他架构问题,但你可以这样做:

    private void Form1_Load(object sender, EventArgs e)
    {
    
        Button btn = new Button();
        btn.Location = new Point(10, 40);
        btn.Text = "Click me";
        btn.Click += new EventHandler(btn_Click);
        btn.Tag = "blahblah";
        this.Controls.Add(btn);
    
    }
    void btn_Click(object sender, EventArgs e)
    {
        Button btn = (Button)sender;
        MessageBox.Show(btn.Tag.ToString());
    }
    

    【讨论】:

    • 很遗憾他们没有原生地制作“通用”winforms 控件。如果没有演员阵容,Tag 可能不会那么混乱。
    【解决方案3】:

    你可以用 lambdas 做到这一点。

    btn.Click += (sender, e) => { MessageBox.Show(blabla); }
    

    【讨论】:

      【解决方案4】:

      你可以像这样在 Form1_Load 方法中做一个闭包

      private void Form1_Load(object sender, EventArgs e)
      {
          blabla = "anything";
      
          Button btn = new Button();
          btn.Location = new Point(10, 40);
          btn.Text = "Click me";
          btn.Click += (s,e) => MessageBox.Show(blabla);
          this.Controls.Add(btn);
      
      }
      

      即使blabla 超出范围,当您单击按钮时,闭包仍然会知道它包含文本“anything”。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-05-28
        • 1970-01-01
        • 1970-01-01
        • 2011-11-28
        • 1970-01-01
        • 1970-01-01
        • 2014-09-18
        • 1970-01-01
        相关资源
        最近更新 更多