유형별로 WPF 컨테이너의 자식을 가져오려면 어떻게 해야 합니까?
유형의 자식 컨트롤을 가져오려면 어떻게 해야 합니까?ComboBox
에MyContainer
Grid
WPF에서요?
<Grid x:Name="MyContainer">
<Label Content="Name" Name="label1" />
<Label Content="State" Name="label2" />
<ComboBox Height="23" HorizontalAlignment="Left" Name="comboBox1"/>
<ComboBox Height="23" HorizontalAlignment="Left" Name="comboBox3" />
<ComboBox Height="23" HorizontalAlignment="Left" Name="comboBox4" />
</Grid>
다음 행에 오류가 표시됩니다.
var myCombobox = this.MyContainer.Children.GetType(ComboBox);
이 확장 메서드는 원하는 유형의 하위 요소를 재귀적으로 검색합니다.
public static T GetChildOfType<T>(this DependencyObject depObj)
where T : DependencyObject
{
if (depObj == null) return null;
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
var child = VisualTreeHelper.GetChild(depObj, i);
var result = (child as T) ?? GetChildOfType<T>(child);
if (result != null) return result;
}
return null;
}
그래서 그걸 이용해서MyContainer.GetChildOfType<ComboBox>()
.
Children은 UILEments의 컬렉션입니다.따라서 항목을 반복하여 각 항목에 대해 필수 유형인지 확인해야 합니다.다행히 이 경우, 즉 Extension Method 구문을 사용하여 쉽게 호출할 수 있는Linq 메서드가 이미 존재합니다.
var comboBoxes = this.MyContainer.Children.OfType<ComboBox>();
이 메서드는 컬렉션을 유형에 따라 필터링하고 유형의 요소만 반환합니다.ComboBox
.
첫 번째 ComboBox(변수 이름에서 알 수 있듯이)만 원하는 경우 다음 쿼리에 콜을 추가할 수 있습니다.
var myComboBox = this.MyContainer.Children.OfType<ComboBox>().FirstOrDefault();
1개를 제외한 모든 답변은 IMO가 그저 어설픈 재귀를 사용합니다.
시각적 하위 항목 가져오기:
public static IEnumerable<T> FindVisualChildren<T>([NotNull] this DependencyObject parent) where T : DependencyObject
{
if (parent == null)
throw new ArgumentNullException(nameof(parent));
var queue = new Queue<DependencyObject>(new[] {parent});
while (queue.Any())
{
var reference = queue.Dequeue();
var count = VisualTreeHelper.GetChildrenCount(reference);
for (var i = 0; i < count; i++)
{
var child = VisualTreeHelper.GetChild(reference, i);
if (child is T children)
yield return children;
queue.Enqueue(child);
}
}
}
논리적인 하위 항목 가져오기:
public static IEnumerable<T> FindLogicalChildren<T>([NotNull] this DependencyObject parent) where T : DependencyObject
{
if (parent == null)
throw new ArgumentNullException(nameof(parent));
var queue = new Queue<DependencyObject>(new[] {parent});
while (queue.Any())
{
var reference = queue.Dequeue();
var children = LogicalTreeHelper.GetChildren(reference);
var objects = children.OfType<DependencyObject>();
foreach (var o in objects)
{
if (o is T child)
yield return child;
queue.Enqueue(o);
}
}
}
양쪽 모두 트리를 깊게 가로지르는 것에 주의해 주세요.처음 접하는 것을 정지하려면 양쪽 코드를 변경하여 콜을 포함시킵니다.queue.Enqueue
에 있어서else
차단합니다.
이 모든 답변은 매우 좋지만, 만약 여러분이 T타입의 특정한 시각적인 아이를 찾으려 한다면, 여러분은 그것들을 모두 얻고 나서 원하는 것을 찾거나, 혹은 여러분이 처음 얻는 것이 여러분이 원하는 것이기를 바랄 것입니다.기준에 따라 특정 방법을 찾기 위해 몇 가지 방법을 병합했습니다.LINQ와 비슷하지만 재귀 열거자를 다루고 싶지는 않습니다.
다음과 같이 사용합니다.
MyContainer.FirstOrDefaultChild<Label>(l => l.Content=="State")
나는 그것을 연장법으로 썼다.
public static class DependencyObjectExtensions
{
public static T FirstOrDefaultChild<T>(this DependencyObject parent, Func<T, bool> selector)
where T : DependencyObject
{
T foundChild;
return FirstOrDefaultVisualChildWhere(parent, selector, out foundChild) ? foundChild : default(T);
}
private static bool FirstOrDefaultVisualChildWhere<T>(DependencyObject parent, Func<T, bool> selector,
out T foundChild) where T : DependencyObject
{
var count = VisualTreeHelper.GetChildrenCount(parent);
for (var i = 0; i < count; i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
var tChild = child as T;
if (tChild != null)
{
if (!selector(tChild)) continue;
foundChild = tChild;
return true;
}
if (FirstOrDefaultVisualChildWhere(child, selector, out foundChild))
{
return true;
}
}
foundChild = default(T);
return false;
}
미리 정해진 지점(화면)을 포함하는 특정 유형의 첫 번째 자식 검색:
(패램 '포인트'는 (Visual type으로 선언된) 'PointToScreen' 함수를 호출한 결과입니다.)
private TDescendantType FindDescendant<TDescendantType>(DependencyObject parent, Point screenPoint)
where TDescendantType : DependencyObject
{
int count = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < count; i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
if (child is Visual)
{
Point point = ((Visual)child).PointFromScreen(screenPoint);
Rect rect = VisualTreeHelper.GetDescendantBounds((Visual)child);
if (!rect.Contains(point))
continue;
}
if (child is TDescendantType)
{
return (TDescendantType)child;
}
child = FindDescendant<TDescendantType>(child, screenPoint);
if (child != null)
{
return (TDescendantType)child;
}
}
return null;
}
다음 작업 예를 찾았습니다.
foreach (object o in LogicalTreeHelper.GetChildren(myWindow))
{
if (o is SomeTypeOfMine)
{
//do something
}
}
출처 : https://social.msdn.microsoft.com/Forums/vstudio/en-US/e0be708a-5fa2-4479-b5a0-8ff44a963803/find-all-child-controls-of-a-type?forum=wpf
언급URL : https://stackoverflow.com/questions/10279092/how-to-get-children-of-a-wpf-container-by-type
'programing' 카테고리의 다른 글
WPF DataTemplate에서 DataType 속성을 사용하려면 어떻게 해야 합니까? (0) | 2023.04.18 |
---|---|
Swift에서 Int를 문자열로 변환 (0) | 2023.04.18 |
NSAttributedString 텍스트 정렬 추가 (0) | 2023.04.18 |
Python의 쌍별 교차 제품 (0) | 2023.04.18 |
다트 목록에서 중복된 항목을 삭제하려면 어떻게 해야 합니까?list.filength()를 선택합니다. (0) | 2023.04.18 |