2

In my WinForms application written in C# there is a Button on one Form which needs to slightly alter the appearance of a second Form (just change the Text on a Button).

I have managed to do this, but the code is horribly long, and I believe there must be a much more concise way of achieving the same thing.

Here is my code for the Button on Form frmConflicts and how it changes the Text on the Button btnAddCase on Form frmAdmin (works, but seems too long) -

private void btnNoConflicts_Click(object sender, EventArgs e)
    {
        try
        {
            foreach (Form f in Application.OpenForms)
            {
                if (f.Name == "frmAdmin")
                {
                    frmAdmin a = (frmAdmin)f;
                    a.conflictsClear = true;
                    foreach (Control ctrl in a.Controls)
                    {
                        if (ctrl.Name == "panAdmin")
                        {
                            foreach (Control ctrl2 in ctrl.Controls)
                            {
                                if (ctrl2.Name == "tabControlAdmin")
                                {
                                    TabControl tab = (TabControl)ctrl2;                                        
                                    foreach(TabPage page in tab.TabPages)
                                    {
                                        if (page.Name == "pageNewCase")
                                        {
                                            foreach (Control ctrl3 in page.Controls)
                                            {
                                                if (ctrl3.Name == "panCaseDetails")
                                                {
                                                    foreach (Control ctrl4 in ctrl3.Controls)
                                                    {
                                                        if (ctrl4.Name == "btnAddCase")
                                                        {
                                                            ctrl4.Text = "Add Case";                                                                
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            this.Close();
        }
        catch (Exception eX)
        {
            MessageBox.Show("frmConflicts: btnNoConflicts()" + Environment.NewLine + eX.Message);
        }

Any help to significantly reduce the amount of code would be much appreciated, as I am going to need to do similar interactions between Forms elsewhere in my application.

4

5 回答 5

5

如果您的按钮是通过设计器添加的并且不是动态创建的,则解决方案很简单:在您的frmAdmin喜欢中添加一个方法

public void ChangeCaption(string caption)
{
     btnAddCase.Text = "Add case";
}

接着

var frmAdmin = Application.OpenForms.OfType<Form>().FirstOrDefault(x => x.GetType() == typeof(frmAdmin));

if (frmAdmin != null)
{
    frmAdmin.ChangeCaption("Add case");
}
于 2013-10-18T10:04:34.760 回答
1

我觉得对你有帮助

foreach (Form f in Application.OpenForms)
{
     var controls =this.Controls.Find("btnAddCase", true);
     if(controls!=null)
        foreach(var control in controls)
        {
            control.Text="Add case";
        }
}
于 2013-10-18T10:10:37.940 回答
1

如果第二个的出现需要对第一个进行更改,您应该以另一种方式解决这个问题。

最好是打开需要更改的按钮以捕获表单二打开的事件,然后应用所需的更改。

在您声明按钮的地方,您应该为其分配一个侦听器,该侦听器将捕获 Form2 打开然后应用操作。

因此,在该方法中,private void btnNoConflicts_Click(object sender, EventArgs e)您应该触发该按钮的事件以捕获而不是搜索它。

于 2013-10-18T10:17:22.470 回答
0

您可以创建一个公共属性并从您的表单订阅 PropertyChanged 事件,您需要具有公共变量的类来扩展 INotifyPropertyChanged。

//Your class
public class ButtonText : INotifyPropertyChanged
{
   private string _buttonText;

   public string ButtonValue
   {
      get{ return _buttonText; }
      set
      {
         //Sets the value of _buttonText to the value passed in an argument 
         _buttonText = value;
         RaisePropertyChanged("ButtonValue");
      }
   }
   protected void RaisePropertyChanged(string propertyName)
   {
      PropertyChangedEventHandler handler = PropertyChanged;
      if (handler != null)
      {
         handler(this, new PropertyChangedEventArgs(propertyName));
      }
   }

   public event PropertyChangedEventHandler PropertyChanged;
}

在您的表单类中,您将绑定到 ButtonText 类的属性 ButtonValue 属性,如下所示:

ButtonText buttonObj = new ButtonText();
//Property field to bind, object to bind, property to bind
btnAddCase.DataBindings.Add("Text", buttonObj,"ButtonValue");
buttonObj.ButtonText = "Your text to bind.";

因为 btnAddCase.Text 属性绑定到 ButtonText 类的 ButtonValue 属性,所以您的 btnAddCase.Text 属性将始终反映您的 ButtonText.ButtonValue 属性的值,它也是一种双向绑定。

于 2013-10-18T10:45:36.197 回答
0

您可以使用 LINQ + ControlCollection.Find

Control btnAddCase = Application.OpenForms.Cast<Form>()
    .Where(f => f.Name == "frmAdmin")
    .SelectMany(f => f.Controls.Find("btnAddCase", true)) // true means recursive
    .FirstOrDefault();
if(btnAddCase != null)
    btnAddCase.Text = "Add Case"; 
于 2013-10-18T10:08:53.137 回答