@@ -135,7 +135,6 @@ public static class LogicalTree
135
135
public static T ? FindChild < T , TState > ( this FrameworkElement element , TState state , Func < T , TState , bool > predicate )
136
136
where T : notnull , FrameworkElement
137
137
{
138
-
139
138
if ( element is Panel panel )
140
139
{
141
140
foreach ( UIElement child in panel . Children )
@@ -282,71 +281,60 @@ public static class LogicalTree
282
281
}
283
282
284
283
/// <summary>
285
- /// Find all logical child controls of the specified type.
284
+ /// Find all logical child elements of the specified element. This method can be chained with
285
+ /// LINQ calls to add additional filters or projections on top of the returned results.
286
+ /// <para>
287
+ /// This method is meant to provide extra flexibility in specific scenarios and it should not
288
+ /// be used when only the first item is being looked for. In those cases, use one of the
289
+ /// available <see cref="FindChild{T}(FrameworkElement)"/> overloads instead, which will
290
+ /// offer a more compact syntax as well as better performance in those cases.
291
+ /// </para>
286
292
/// </summary>
287
- /// <typeparam name="T">Type to search for.</typeparam>
288
- /// <param name="element">Parent element.</param>
289
- /// <returns>Child controls or empty if not found.</returns>
290
- public static IEnumerable < T > FindChildren < T > ( this FrameworkElement element )
291
- where T : FrameworkElement
293
+ /// <param name="element">The root element.</param>
294
+ /// <returns>All the child <see cref="FrameworkElement"/> instance from <paramref name="element"/>.</returns>
295
+ public static IEnumerable < FrameworkElement > FindChildren ( this FrameworkElement element )
292
296
{
293
- if ( element == null )
294
- {
295
- yield break ;
296
- }
297
-
298
- if ( element is Panel )
297
+ if ( element is Panel panel )
299
298
{
300
- foreach ( var child in ( element as Panel ) . Children )
299
+ foreach ( UIElement child in panel . Children )
301
300
{
302
- if ( child is T )
301
+ if ( child is not FrameworkElement current )
303
302
{
304
- yield return child as T ;
303
+ continue ;
305
304
}
306
305
307
- var childFrameworkElement = child as FrameworkElement ;
306
+ yield return current ;
308
307
309
- if ( childFrameworkElement != null )
308
+ foreach ( FrameworkElement childOfChild in FindChildren ( current ) )
310
309
{
311
- foreach ( T childOfChild in childFrameworkElement . FindChildren < T > ( ) )
312
- {
313
- yield return childOfChild ;
314
- }
310
+ yield return childOfChild ;
315
311
}
316
312
}
317
313
}
318
- else if ( element is ItemsControl )
314
+ else if ( element is ItemsControl itemsControl )
319
315
{
320
- foreach ( var item in ( element as ItemsControl ) . Items )
316
+ foreach ( object item in itemsControl . Items )
321
317
{
322
- var childFrameworkElement = item as FrameworkElement ;
318
+ if ( item is not FrameworkElement current )
319
+ {
320
+ continue ;
321
+ }
323
322
324
- if ( childFrameworkElement != null )
323
+ yield return current ;
324
+
325
+ foreach ( FrameworkElement childOfChild in FindChildren ( current ) )
325
326
{
326
- foreach ( T childOfChild in childFrameworkElement . FindChildren < T > ( ) )
327
- {
328
- yield return childOfChild ;
329
- }
327
+ yield return childOfChild ;
330
328
}
331
329
}
332
330
}
333
- else
331
+ else if ( element . TryGetContentControl ( ) is FrameworkElement contentControl )
334
332
{
335
- var content = element . TryGetContentControl ( ) ;
333
+ yield return contentControl ;
336
334
337
- if ( content is T )
335
+ foreach ( FrameworkElement childOfChild in FindChildren ( contentControl ) )
338
336
{
339
- yield return content as T ;
340
- }
341
-
342
- var childFrameworkElement = content as FrameworkElement ;
343
-
344
- if ( childFrameworkElement != null )
345
- {
346
- foreach ( T childOfChild in childFrameworkElement . FindChildren < T > ( ) )
347
- {
348
- yield return childOfChild ;
349
- }
337
+ yield return childOfChild ;
350
338
}
351
339
}
352
340
}
@@ -544,6 +532,33 @@ public static IEnumerable<T> FindChildren<T>(this FrameworkElement element)
544
532
return FindParent ( element , state , predicate ) ;
545
533
}
546
534
535
+ /// <summary>
536
+ /// Find all parent elements of the specified element. This method can be chained with
537
+ /// LINQ calls to add additional filters or projections on top of the returned results.
538
+ /// <para>
539
+ /// This method is meant to provide extra flexibility in specific scenarios and it should not
540
+ /// be used when only the first item is being looked for. In those cases, use one of the
541
+ /// available <see cref="FindParent{T}(FrameworkElement)"/> overloads instead, which will
542
+ /// offer a more compact syntax as well as better performance in those cases.
543
+ /// </para>
544
+ /// </summary>
545
+ /// <param name="element">The root element.</param>
546
+ /// <returns>All the parent <see cref="FrameworkElement"/> instance from <paramref name="element"/>.</returns>
547
+ public static IEnumerable < FrameworkElement > FindParents ( this FrameworkElement element )
548
+ {
549
+ while ( true )
550
+ {
551
+ if ( element . Parent is not FrameworkElement parent )
552
+ {
553
+ yield break ;
554
+ }
555
+
556
+ yield return parent ;
557
+
558
+ element = parent ;
559
+ }
560
+ }
561
+
547
562
/// <summary>
548
563
/// Tries to retrieve the content property of this element as defined by <see cref="ContentPropertyAttribute"/>.
549
564
/// </summary>
0 commit comments