2013-10-18 34 views
2

在我用C#编写的WinForms应用程序中,在一个表单上有一个按钮,需要稍微改变第二个表单的外观(只需更改按钮上的文本)。需要一种更好的方式来遍历表单控件

我已经做到了这一点,但代码非常长,我相信必须有一个更简洁的方法来实现同样的事情。

这里是我的表格frmConflicts按钮代码和它如何改变上表frmAdmin按钮btnAddCase文本(的作品,但似乎太长) -

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); 
     } 

任何有助于显著减少量的代码将非常感谢,因为我需要在我的应用程序中其他地方的窗体之间进行类似的交互。

回答

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"); 
} 
+0

这个答案的简单性与我所拥有的相比是不可否认的 - 非常感谢你。 – PJW

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"; 
+0

这是一个启发式代码示例。它可能有效,但可能会产生意想不到的结果 –

+0

@Vash:OP只要求代码相同,但更简洁(_“显着减少代码量将不胜感激”_)。这里是。它也是安全的,如果你改变一个名字,它不会抛出异常。 –

+0

这是真的在Gzaxx答案见。它符合OP的要求,并且可以在任何情况下工作。你的方法中的问题是,如果有两个'btnAddCase'放置在'frmAdmin'层次结构的某处,那么你的代码可能会失败。 –

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"; 
     } 
} 
1

如果第二个从第一个你需要改变的外观应该以另一种方式解决这个问题。

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

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

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

+0

最后,我很震惊没有人更早指出这一点......不典型的SOF – Bolu

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属性的值,这也是一种双向绑定。

相关问题