在我的应用程序中,我有一些函数可以循环访问表单中的所有组件,以建立一些类似于以下属性的属性:
用于仅在查看数据时将表单中的所有文本框设置为只读的函数:
public void SetReadOnly(Control.ControlCollection controls, bool readOnly)
{
foreach(var panel in controls.OfType<Panel>())
{
SetReadOnly(panel.Controls, readOnly);
}
foreach(var tabpageview in controls.OfType<TabPageView>())
{
foreach(var tabpageviewpage in tabpage.Controls)
{
SetReadOnly(tagpageviewpage.Controls, readOnly);
}
}
foreach(var textbox in controls.OfType<TextBox>())
{
textbox.ReadOnly = readOnly;
}
}
用于将数据插入数据库后清除所有文本框内容的函数:
public void CleanTextBox(Control.ControlCollection controls)
{
foreach(var panel in controls.OfType<Panel>())
{
CleanTextBox(panel.Controls);
}
foreach(var tabpageview in controls.OfType<TabPageView>())
{
foreach(var tabpageviewpage in tabpage.Controls)
{
CleanTextBox(tagpageviewpage.Controls);
}
}
foreach(var textbox in controls.OfType<TextBox>())
{
textbox.Text = "";
}
}
该函数将接收字段列表,并将带有该名称的标签涂成红色以标记必填项:
public void SetRequired(Control.ControlCollection controls, List<string> requiredFields)
{
foreach(var panel in controls.OfType<Panel>())
{
SetRequired(panel.Controls, requiredFields);
}
foreach(var tabpageview in controls.OfType<TabPageView>())
{
foreach(var tabpageviewpage in tabpage.Controls)
{
SetRequired(tagpageviewpage.Controls, requiredFields);
}
}
foreach(var field in requiredFields)
{
FindLabelByName(field).Foreground(Color.Red);
}
}
如您所见,所有这些函数都有一些共同点,它们会收到一组控件并在它们上循环。如果它是面板,tabpageview或具有子元素的其他组件,则它将再次循环直到找到其文本框并执行一些操作。
是否可以使一个函数接收另一个函数作为参数,所以如果我开始使用组框,可以将其放在一个函数中,而不必将其放在所有函数中?像这样的东西。
public void LoopComponents(Control.ControlCollection controls, xxx function)
{
foreach(var panel in controls.OfType<Panel>())
{
LoopComponents(panel.controls, function);
}
foreach(var tabpageview in controls.OfType<TabPageView>())
{
foreach(var tabpageviewpage in tabpageview.Controls)
{
LoopComponents(tabpageviewpage.Controls, function);
}
}
function();
}
public void SetReadOnly(Control.ControlCollection controls, bool readOnly)
{
foreach(var textbox in controls.OfType<TextBox>())
{
textbox.ReadOnly = readOnly;
}
}
public void CleanTextBox(Control.ControlCollection controls)
{
foreach(var textbox in controls.OfType<TextBox>())
{
textbox.Text = "";
}
}
public void SetRequired(Control.ControlCollection controls, List<string> requiredFields)
{
foreach(var field in requiredFields)
{
FindLabelByName(field).Foreground(Color.Red);
}
}
public void Test()
{
LoopComponents(Controls, SetReadOnly(Controls, true));
LoopComponents(Controls, CleanTextBox(Controls));
LoopComponents(Controls, SetRequired(Controls, requiredFieldsList));
}
当前我正在使用C#4.0,但是如果在更高版本中可以使用,则没关系,只是好奇地知道是否可能。谢谢
答案 0 :(得分:0)
您必须定义一个委托或使用预定义的委托,例如Action <>和Func <>。 代表将定义方法签名:
delegate void Operator(Control.ControlCollection controls);
,您可以通过以下方式修改LoadComponent:
LoadComponent(Control.ControlCollection controls, Operator Op)
{
foreach(var control in controls.OfType<Panel>())
{
Op(panel.controls);
}
//....
}
,您可以编写一些运算符,例如:
public void CleanTextBox(Control.ControlCollection controls)
{
foreach(var textbox in controls.OfType<TextBox>())
{
textbox.Text = "";
}
}
注意:上述功能CleanTextBox
中的输入和输出在操作员委托中相同。因此它将与操作员委托匹配。
使用预定义的委托人:
您可以使用预定义的委托。由于您的函数无效,因此可以使用Action的重载之一:
LoadComponent(Action<Control.ControlCollection controls, Action<Control.ControlCollection> Op)
{
foreach(var control in controls.OfType<Panel>())
{
Op(panel.controls);
}
//....
}
此新版本刚刚删除了代理减速度。 在两种工作方式中,您都可以使用以下代码对数据进行操作:
LoopComponents(Controls, CleanTextBox(Controls));
**当您希望有一个返回值时,Func委托很有用**
编辑:如果要使用一个委托调用不同的方法,则必须创建新方法来统一这些方法:
重写LoadComponents
:
LoadComponents(Control.ControlCollection controls, Action Op)
{
Op.Invoke();
//....
}
(这是Lambda表达式,用于统一您的方法)
LoadComponents(Controls, new Action(()=>{ SetRequired(Controls,true);}));
LoopComponents(Controls, new Action(()=>{ CleanTextBox(Controls);}));
LoopComponents(Controls, new Action(()=>{ SetRequired(Controls, requiredFieldsList);});