【问题标题】:Referring to programmatically created button and it's click event指以编程方式创建的按钮及其点击事件
【发布时间】:2012-03-23 12:17:55
【问题描述】:

对于android 的mono,我绝对是初学者。

我使用以下代码 sn-p 以编程方式创建 50 个按钮:

for(int i=0;i<50;i++)
            {
            //code to calculate x and y position
                btn=new Button(this);
                //btn.SetBackgroundColor(Android.Resource.Color.);
                btn.SetTextSize(Android.Util.ComplexUnitType.Sp,8);
                btn.Text="Scrip "+i+"\n"+"CMP "+i+"\n"+"%Chg "+i;
                lp = new RelativeLayout.LayoutParams(new ViewGroup.MarginLayoutParams((width+30)/5, (height-10)/10));
                btn.LayoutParameters=lp;
                lp.SetMargins(leftMargin,topMargin, 0, 0);
                main.AddView(btn);
            }
            
            String str="";
            btn.Click += (sender, e) => 
            {
                str=btn.Text;
                Toast.MakeText(this, "Selected="+str,ToastLength.Short).Show();
                Console.WriteLine("Selected="+str);
            };

但是这段代码的一个大问题是在循环结束时,btn 对象只有最后一个按钮的引用。

因此,如果按下最后一个按钮以外的任何按钮,则不会触发 button click 事件。 如何解决? 理想情况下,它应该返回点击按钮的文本。

另外,参考下面的截图,这里的默认按钮样式看起来不太好。所以我想把它改成精确的矩形而不是圆角矩形(默认的)。 对此有什么想法吗?

由于我对此很陌生,任何帮助将不胜感激!

编辑

在您的帮助下,我能够正确地创建和引用所有按钮。

但是如何将它们的样式设置为精确的矩形呢?

【问题讨论】:

    标签: c# android button xamarin.android


    【解决方案1】:

    btn.Click += (sender, e) 订阅移动到 for 循环中。

    更好 - 创建一个命名方法而不是创建许多匿名方法。例如。 Button_Click 并订阅它:

    btn = new Button(this);
    btn.Click = Button_Click;
    

    在该方法中,您可以将 sender 对象转换为 Button 并知道单击了哪个按钮。

    更新:这里是完整的代码

    const int rowsCount = 10;
    const int columnsCount = 5;
    int buttonsCount = rowsCount * columnsCount;
    
    for (int i = 0; i < buttonsCount; i++)            
        AddButton();
    

    我不喜欢在代码中使用幻数:)

    private void AddButton()
    {
        Button button = new Button(this);
        button.Click += Button_Click;
        // add text and other properties
        main.AddView(button);
    }
    
    private void Button_Click(object sender, EventArgs e)
    {
        Button button = (sender as Button);
        // use clicked button e.g. Console.WriteLine("Selected = {0}", button.Text);
    }
    

    【讨论】:

    • 谢谢。但是你能提供我如何“将发件人对象转换为按钮并知道单击了哪个按钮”的sn-p吗?这将非常有帮助...
    • @GAMA 这是正确答案。转换发件人对象很简单:Button b = sender as Button
    • 是的,您可以按照 NominSim 的说明进行操作。投射后,对象 b 将恰好是按下的那个按钮。你可以得到它的属性,比如 b.Text
    【解决方案2】:

    您的 for 循环对一个按钮进行操作并每次创建一个新实例,但您的 click 事件仅添加一次(它在您的 for 循环之外)。因此,它只会添加到放入 btn 的最后一个 Button 实例(for 循环中的最后一个按钮)。

    您需要单独创建每个按钮(例如将它们放在列表中),然后在 for 循环之外,您将获得对每个按钮的引用,您可以将单击事件单独添加到每个按钮。或者(更好的方法)在 for 循环中添加 click 事件,以便您创建的每个按钮都遵循它。请记住,由于事件将通过任意按钮(您的 50 个按钮之一)到达,因此最好使用 sender 参数来确定其文本值。 即:

            btn.Click += (sender, e) => 
            {
                Button b = sender as Button;
                if ( b == null ) return;
                String str;
                str=b.Text;
                Toast.MakeText(this, "Selected="+str,ToastLength.Short).Show();
                Console.WriteLine("Selected="+str);
            };
    

    【讨论】:

      【解决方案3】:

      你已经创建了 50 个按钮,所以你需要有 50 个对它的引用。实现这一点的最简单方法是创建一个按钮数组,如下所示:

             Button[] btns = new Button[50];
             for(int i=0;i<50;i++)
             {
                  {
                  //code to calculate x and y position
                      btns[i]=new Button(this);
                      //btn.SetBackgroundColor(Android.Resource.Color.);
                      btns[i].SetTextSize(Android.Util.ComplexUnitType.Sp,8);
                      btns[i].Text="Scrip "+i+"\n"+"CMP "+i+"\n"+"%Chg "+i;
                      lp = new RelativeLayout.LayoutParams(new ViewGroup.MarginLayoutParams((width+30)/5, (height-10)/10));
                      btns[i].LayoutParameters=lp;
                      lp.SetMargins(leftMargin,topMargin, 0, 0);
                      main.AddView(btn);
                  }
      
                  btns[i].Click += (sender, e) => 
                  {
                      String str= ( (sender as Button) != null) ? (sender as Button).Content.ToString() : "";
                      Toast.MakeText(this, "Selected="+str,ToastLength.Short).Show();
                      Console.WriteLine("Selected="+str);
                  }
              }
      

      //编辑:您还需要为每个按钮创建一个事件处理程序

      【讨论】:

      • 他可以通过在事件处理程序中强制转换(发送者为按钮)来获得对按钮的引用。因此,不需要 Buttons 数组。
      • String str= ( (sender as Button) != null) ? (sender as Button).Content.ToString() : ""; 给我以下错误:Android.Widget.Button does not contain definition for 'Content' and no extension Method 'Content' accepting first argument of type Android.Widget.Button can be found...
      • 同意@lazyberezovsky 不需要 Buttons 数组
      【解决方案4】:

      这是因为您在 for 循环之外设置了按钮单击事件。把它放在里面,这样它就会被分配给每个按钮,而不仅仅是最后一个。

      【讨论】:

        猜你喜欢
        • 2017-06-21
        • 1970-01-01
        • 2017-10-14
        • 2023-03-03
        • 2013-05-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多