有没有一种 LINQy 方法可以将所有 ReadOnly 控件的 TabStop 设置为 false?
Is there a LINQy way to set all ReadOnly controls' TabStop to false?
我正在使用以下代码将 ReadOnly 属性 为 true 的所有控件的 TabStop 属性 设置为 false:
foreach (Control control in this.Controls)
{
if (control is TextBox)
{
//if (((TextBox)control).ReadOnly)
//{
// control.TabStop = false;
//}
control.TabStop = (!((TextBox)control).ReadOnly);
}
}
...但我认为可能有更多 "modern" (elegant/fancy) 的方式来执行此操作,可能使用 LINQ。
更新
好的,所以我认为,根据答案,这可行:
private void FrmDelivery_Load(object sender, EventArgs e)
{
var q = Controls.SelectMany(c => Walk(c)).OfType<TextBox>().Where(c
=> c.ReadOnly);
foreach (var control in q)
{
control.TabStop = false;
}
}
IEnumerable<Control> Walk(Control control)
{
yield return control;
foreach (var child in control.Controls.SelectMany(c=> Walk(c)))
{
yield return c;
}
}
...但我得到:
"'System.Windows.Forms.Control.ControlCollection' 不包含 'SelectMany' 的定义,并且找不到接受类型 'System.Windows.Forms.Control.ControlCollection' 的第一个参数的扩展方法 'SelectMany' (您是否缺少 using 指令或程序集引用?)"
-在使用 SelectMany 的两种情况下(它似乎无法解析);并且,在 "yield return c" 行:
"当前上下文中不存在名称 'c'"
更新 2
对于我的简单场景(控件中没有容器/控件),这可行
foreach (Control control in this.Controls)
{
var txtbx = control as TextBox;
if (txtbx != null)
{
txtbx.TabStop = (!txtbx.ReadOnly);
}
}
foreach (TextBox control in this.Controls.OfType<TextBox>())
要对您的示例进行 linqify:
foreach (var control in Controls.OfType<TextBox>().Where(c => c.ReadOnly)
{
control.TabStop = false;
}
但是,您的示例不会处理所有控件,因为控件可以包含其他控件。您将需要一个递归下降算法。
IEnumerable<Control> Walk(Control control)
{
yield return control;
foreach (var child in control.Controls.SelectMany(c=> Walk(c)))
{
yield return c;
}
}
var q = Controls
.SelectMany(c => Walk(c))
.OfType<TextBox>().
.Where(c => c.ReadOnly);
foreach (var control in q)
{
control.TabStop = false;
}
不是最高性能的代码,也不是最易读的代码,但您可以通过以下方式将其作为单行代码完成:
this.Controls.OfType<TextBox>().ToList().ForEach(t => t.TabStop = !t.ReadOnly);
...只是为了证明你可以。
我正在使用以下代码将 ReadOnly 属性 为 true 的所有控件的 TabStop 属性 设置为 false:
foreach (Control control in this.Controls)
{
if (control is TextBox)
{
//if (((TextBox)control).ReadOnly)
//{
// control.TabStop = false;
//}
control.TabStop = (!((TextBox)control).ReadOnly);
}
}
...但我认为可能有更多 "modern" (elegant/fancy) 的方式来执行此操作,可能使用 LINQ。
更新
好的,所以我认为,根据答案,这可行:
private void FrmDelivery_Load(object sender, EventArgs e)
{
var q = Controls.SelectMany(c => Walk(c)).OfType<TextBox>().Where(c
=> c.ReadOnly);
foreach (var control in q)
{
control.TabStop = false;
}
}
IEnumerable<Control> Walk(Control control)
{
yield return control;
foreach (var child in control.Controls.SelectMany(c=> Walk(c)))
{
yield return c;
}
}
...但我得到:
"'System.Windows.Forms.Control.ControlCollection' 不包含 'SelectMany' 的定义,并且找不到接受类型 'System.Windows.Forms.Control.ControlCollection' 的第一个参数的扩展方法 'SelectMany' (您是否缺少 using 指令或程序集引用?)"
-在使用 SelectMany 的两种情况下(它似乎无法解析);并且,在 "yield return c" 行:
"当前上下文中不存在名称 'c'"
更新 2
对于我的简单场景(控件中没有容器/控件),这可行
foreach (Control control in this.Controls)
{
var txtbx = control as TextBox;
if (txtbx != null)
{
txtbx.TabStop = (!txtbx.ReadOnly);
}
}
foreach (TextBox control in this.Controls.OfType<TextBox>())
要对您的示例进行 linqify:
foreach (var control in Controls.OfType<TextBox>().Where(c => c.ReadOnly)
{
control.TabStop = false;
}
但是,您的示例不会处理所有控件,因为控件可以包含其他控件。您将需要一个递归下降算法。
IEnumerable<Control> Walk(Control control)
{
yield return control;
foreach (var child in control.Controls.SelectMany(c=> Walk(c)))
{
yield return c;
}
}
var q = Controls
.SelectMany(c => Walk(c))
.OfType<TextBox>().
.Where(c => c.ReadOnly);
foreach (var control in q)
{
control.TabStop = false;
}
不是最高性能的代码,也不是最易读的代码,但您可以通过以下方式将其作为单行代码完成:
this.Controls.OfType<TextBox>().ToList().ForEach(t => t.TabStop = !t.ReadOnly);
...只是为了证明你可以。