1. 개요
Winform/WPF를 사용하다보면 UI의 값을 특정 파일에 저장해 두거나,
이후 UI가 Load 될 때 UI 내부 각 컨트롤에 필요한 값을 설정하는 작업이 필요할 때가 있다.
이를 위해서 WPF UI 내부의 모든 컨트롤을 가져오거나, 사용자가 선택한 타입의 컨트롤만 가져오는 메서드가 필요하다.
Winform에서 UI 내부 컨트롤 중 사용자가 설정한 컨트롤의 리스트를 가져오는 방법은 예전 글로 작성한 바 있다.
WPF에서는 UI 내부 컨트롤을 가져오는 방법으로 VisualTreeHelper를 이용한 방법과 LogicalTreeHelper를 이용한 방법이 있다. 두 방법의 사용법은 유사하지만, 현재까지 사용해본 결과 LogicalTreeHelper를 이용한 방법이 더 나은 것 같다. 각각의 방식에 대한 설명과 차이점은 아래와 같다.
2. VisualTreeHelper를 이용한 방법
VisualTreeHelper의 GetChild 메서드를 통해 DependencyObject를 가져오고, 내부의 foreach 반복문으로 계속 자식 컨트롤을 찾아낸다. 아래 메서드 및 사용 예를 작성하였다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
using System.Collections.Generic;
using System.Windows.Controls;
using System.Window;
public static IEnumerable<T> FindWindowChildren<T>(DependencyObject dObj) where T : DependencyObject
{
if (dObj != null)
{
for (int i = 0; i < System.Windows.Media.VisualTreeHelper.GetChildrenCount(dObj); i++)
{
DependencyObject ch = System.Windows.Media.VisualTreeHelper.GetChild(dObj, i);
if (ch != null && ch is T)
{
yield return (T)ch;
}
foreach (T nestedChild in FindWindowChildren<T>(ch))
{
yield return nestedChild;
}
}
}
}
|
cs |
코드 사용 예
1
|
IEnumerable<TextBox> textboxList = FindWindowChildren<TextBox>(form);
|
cs |
3. LogicalTreeHelper를 이용한 방법
VisualTreeHelper와 마찬가지로 GetChildren 메서드를 통해 자식 컨트롤을 찾고, 재귀함수로 계속해서 찾아나가는 방식이다. LogicalTreeHelper에서 IEnumerable은 System.Collections로부터 가져오는 것이므로 using문을 주의해야하고, 반드시 정적(static) 클래스에서 사용해야한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
using System.Collections;
using System.Windows.Controls;
using System.Window;
public static class Get_WPF_Control
{
public static List<T> GetLogicalChildCollection<T>(this DependencyObject parent) where T : DependencyObject
{
List<T> logicalCollection = new List<T>();
GetLogicalChildCollection(parent, logicalCollection);
return logicalCollection;
}
private static void GetLogicalChildCollection<T>(DependencyObject parent, List<T> logicalCollection) where T : DependencyObject
{
IEnumerable children = LogicalTreeHelper.GetChildren(parent);
foreach (object child in children)
{
if (child is DependencyObject)
{
DependencyObject depChild = child as DependencyObject;
if (child is T)
{
logicalCollection.Add(child as T);
}
GetLogicalChildCollection(depChild, logicalCollection);
}
}
}
}
|
cs |
코드 사용 예
1
|
List<TextBox> textboxList = Get_WPF_Control.GetLogicalChildCollection<TextBox>(form);
|
cs |
4. 차이점
VisualTreeHelper를 이용한 방법과 LogicalTreeHelper를 이용한 방법 둘다 사용 방식은 유사해 보이지만, 실제로 동작해보면 그 차이점을 알 수 있다.
- VisualTreeHelper를 이용한 방법은 현재 UI에서 보이는 컨트롤의 정보만 가져올 수 있다.
예를 들어 Expander가 접힌 상태(IsExpanded = False)라면 Expander 내부의 컨트롤은 가져올 수 없다. - LogicalTreeHelper를 이용한 방법은 현재 UI에서 보이지 않는 컨트롤의 정보까지 가져올 수 있다.
위의 예시에서 Expander가 접힌 상태여도 Expander 내부의 컨트롤을 가져올 수 있다.
5. 결론
추후 사용 시 LogicalTreeHelper를 사용한 방법에 문제가 없다면 VisualTreeHelper보다는 LogicalTreeHelper를 사용한 방법으로 모든 UI 내부의 WPF 컨트롤을 가져오는 방법이 더 낫다.
'프로그래밍 언어 > WPF' 카테고리의 다른 글
[C#] WPF - Round Button 생성 (0) | 2024.04.08 |
---|---|
[C#] WPF - 사용자 정의 컨트롤(User Control) / 사용자 지정 컨트롤(Custom Control) (0) | 2024.01.09 |
[C#] WPF - 토글 스위치(Toggle Switch) 생성 (2) | 2023.12.26 |
[C#] WPF - 특정 프로세스 Focus 여부 판단 방법 (0) | 2023.01.09 |
[C#] WPF - DataGrid의 ForeColor 변경 시 에러 방지 (2) | 2022.10.26 |
댓글