x 유형의 양식에 대한 모든 컨트롤을 가져와야합니다. 나는 과거에 다음과 같은 코드를 사용한 코드를 한 번 보았다고 확신합니다.
dim ctrls() as Control
ctrls = Me.Controls(GetType(TextBox))
재귀 함수를 사용하여 자식을 가져 오는 모든 컨트롤을 반복 할 수 있다는 것을 알고 있지만 다음과 같이 더 쉽고 간단한 것이 있습니까?
Dim Ctrls = From ctrl In Me.Controls Where ctrl.GetType Is Textbox
답변
여기에 또 다른 옵션이 있습니다. 샘플 애플리케이션을 만들어 테스트 한 다음 초기 GroupBox 안에 GroupBox와 GroupBox를 넣었습니다. 중첩 된 GroupBox 안에 3 개의 TextBox 컨트롤과 버튼이 있습니다. 이것은 내가 사용한 코드입니다 (찾고 있던 재귀도 포함)
public IEnumerable<Control> GetAll(Control control,Type type)
{
var controls = control.Controls.Cast<Control>();
return controls.SelectMany(ctrl => GetAll(ctrl,type))
.Concat(controls)
.Where(c => c.GetType() == type);
}
양식로드 이벤트에서 테스트하기 위해 초기 GroupBox 내부의 모든 컨트롤 수를 원했습니다.
private void Form1_Load(object sender, EventArgs e)
{
var c = GetAll(this,typeof(TextBox));
MessageBox.Show("Total Controls: " + c.Count());
}
그리고 그것은 매번 적절한 카운트를 반환했기 때문에 이것이 당신이 찾고있는 것에 완벽하게 작동 할 것이라고 생각합니다 🙂
답변
C #에서는 태그를 지정 했으므로 다음과 같은 LINQ 식을 사용할 수 있습니다.
List<Control> c = Controls.OfType<TextBox>().Cast<Control>().ToList();
재귀 편집 :
이 예제에서는 먼저 컨트롤 목록을 만든 다음이를 채우는 메서드를 호출합니다. 메서드가 재귀 적이므로 목록을 반환하지 않고 업데이트 만합니다.
List<Control> ControlList = new List<Control>();
private void GetAllControls(Control container)
{
foreach (Control c in container.Controls)
{
GetAllControls(c);
if (c is TextBox) ControlList.Add(c);
}
}
Descendants
내가 익숙하지는 않지만 함수를 사용하여 하나의 LINQ 문에서이 작업을 수행 할 수 있습니다 . 이 페이지 보기 대한 자세한 내용 를 .
컬렉션을 반환하려면 2를 편집합니다.
@ProfK가 제안했듯이 원하는 컨트롤을 단순히 반환하는 방법이 아마도 더 나은 방법 일 것입니다. 이를 설명하기 위해 다음과 같이 코드를 수정했습니다.
private IEnumerable<Control> GetAllTextBoxControls(Control container)
{
List<Control> controlList = new List<Control>();
foreach (Control c in container.Controls)
{
controlList.AddRange(GetAllTextBoxControls(c));
if (c is TextBox)
controlList.Add(c);
}
return controlList;
}
답변
이것은 실제로 private vars에서 작동하는 재귀 GetAllControls ()의 개선 된 버전입니다 :
private void Test()
{
List<Control> allTextboxes = GetAllControls(this);
}
private List<Control> GetAllControls(Control container, List<Control> list)
{
foreach (Control c in container.Controls)
{
if (c is TextBox) list.Add(c);
if (c.Controls.Count > 0)
list = GetAllControls(c, list);
}
return list;
}
private List<Control> GetAllControls(Control container)
{
return GetAllControls(container, new List<Control>());
}
답변
이전의 여러 아이디어를 하나의 확장 방법으로 결합했습니다. 여기서 이점은 올바르게 입력 된 열거 형을 다시 가져오고 상속이 OfType()
.
public static IEnumerable<T> FindAllChildrenByType<T>(this Control control)
{
IEnumerable<Control> controls = control.Controls.Cast<Control>();
return controls
.OfType<T>()
.Concat<T>(controls.SelectMany<Control, T>(ctrl => FindAllChildrenByType<T>(ctrl)));
}
답변
LINQ 쿼리를 사용하여이를 수행 할 수 있습니다. 이것은 TextBox 유형 인 양식의 모든 것을 쿼리합니다.
var c = from controls in this.Controls.OfType<TextBox>()
select controls;
답변
고대의 기술일지도 모르지만 매력처럼 작동합니다. 컨트롤의 모든 레이블 색상을 변경하기 위해 재귀를 사용했습니다. 잘 작동합니다.
internal static void changeControlColour(Control f, Color color)
{
foreach (Control c in f.Controls)
{
// MessageBox.Show(c.GetType().ToString());
if (c.HasChildren)
{
changeControlColour(c, color);
}
else
if (c is Label)
{
Label lll = (Label)c;
lll.ForeColor = color;
}
}
}
답변
PsychoCoders 답변을 수정하고 싶습니다. 사용자가 특정 유형의 모든 컨트롤을 얻으려면 다음과 같은 방법으로 제네릭을 사용할 수 있습니다.
public IEnumerable<T> FindControls<T>(Control control) where T : Control
{
// we can't cast here because some controls in here will most likely not be <T>
var controls = control.Controls.Cast<Control>();
return controls.SelectMany(ctrl => FindControls<T>(ctrl))
.Concat(controls)
.Where(c => c.GetType() == typeof(T)).Cast<T>();
}
이렇게하면 다음과 같이 함수를 호출 할 수 있습니다.
private void Form1_Load(object sender, EventArgs e)
{
var c = FindControls<TextBox>(this);
MessageBox.Show("Total Controls: " + c.Count());
}