2

I've got a window with some expanders in it. When you open a expander there is some information inside it.

What i need to do is to open all expanders with one button so everything inside them becomes visible. When everything is visible i want to print the full page.

This is my code for expanding all expanders now:

public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
{
    if (depObj != null)
    {
        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
        {
            DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
            if (child != null && child is T)
            {
                yield return (T)child;
            }

            foreach (T childOfChild in FindVisualChildren<T>(child))
            {
                yield return childOfChild;
            }
        }
    }
}

The lines i use to iterate through my controls:

foreach (Expander exp in FindVisualChildren<Expander>(printpage))
{
    exp.IsExpanded = true;
}

Now to the point:

The code above works in most cases. The only problem i have is that sometimes there are some expanders WITHIN expanders. The parent expanders do expand when the above code executes, The child expanders however remain unexpanded.

I hope someone can teach me how to expand those child expanders too.

EDIT
I forgot to mention that the child-expanders are not direct childs of the main expanders..
They are children of children of children of the main expanders.

My controll-tree goes something like this:

-Stackpanel
---List item
-----Grid
-------Expander (Main expanders)
---------Grid
-----------Textblock
-------------Expander

So i need to expand all expanders in this tree.

NickGames
  • 312
  • 1
  • 18
  • 1
    I have edited your title. Please see, "[Should questions include “tags” in their titles?](http://meta.stackexchange.com/questions/19190/)", where the consensus is "no, they should not". – John Saunders Jan 14 '15 at 15:54
  • why not check the children of the expander and if the are expander repeat until all are open – ZoomVirus Jan 14 '15 at 16:26
  • Do you know why it fails, when it fails? Does `FindVisualChildren` not contain the inner `Expander`? Is `IsExpanded` set to `true`, but WPF doesn't recalculate the layout? – Niki Jan 14 '15 at 16:44

3 Answers3

1

Your code is quite complicated already for what it does. Yields are absolutely not necessary if you call and you really should to execute your method in a recursive fashion.

When, inside your method you encounter a control with children, you call the same method but with a new visual root, which will be a control with children you've just found.

zmechanic
  • 1,842
  • 21
  • 27
  • 1
    What you're suggesting sounds like mixing the "recursive enumeration" logic and the "expand logic" in the same function - which is less readable and less reusable. I don't think that would be an improvement. – Niki Jan 14 '15 at 16:19
  • For reusability purpose you can pass Action<> as a second parameter into your recursive method. This way you separate enumeration from action. – zmechanic Jan 14 '15 at 16:27
  • Sure, but then it's as complex as the `yield` version, but less flexible: For example, you can use `Enumerable.Where`, `Enumerable.Select`, `Enumerable.Count`&friends on the enumerable version. – Niki Jan 14 '15 at 16:33
  • Valid point. But you've asked how to expand all children, not how to enumerate children on all levels. – zmechanic Jan 14 '15 at 16:56
  • I need to expand all children, but the child-expanders are not direct-childs of the main expanders. They're children of children of children of the main expanders. – NickGames Jan 15 '15 at 06:15
  • Doesn't matter, because recursive function iterates until all children are exhausted. – zmechanic Jan 15 '15 at 12:01
0

This should work for you (may be a few syntax errors but i'm sure if there are you can fix them)

foreach (Expander exp in FindVisualChildren<Expander>(printpage))
{
    exp.IsExpanded = true;
    for(int i =0;i<exp.Children.Count;i++)
    {
        if(exp.Children[i] is Expander)
        {
             expandChildren(exp.Children[i]);
        }
    }
}

private expandChildren(Expander exp)
{
    exp.IsExpanded = true;
    for(int i =0;i<exp.Children.Count;i++)
    {
        if(exp.Children[i] is Expander)
        {
             expandChildren(exp.Children[i]);
        }
    }       
}
ZoomVirus
  • 615
  • 7
  • 22
  • You should not copy your code twice. Just call `expandChildren` in the first loop. Any be sure you use `FindVisualChildren` again, as they are not direct children. – Scoregraphic Jan 15 '15 at 06:51
  • Your code doesn't work.. Expanders don't have a children property.. Only content. So when the script expands an expander and searches for the expanders children, it can't find any children( with VisualTreeHelper.GetChildrenCount(expander)). – NickGames Jan 15 '15 at 08:13
0

Okay, I found my anwser in this post

The anwser on this question is what I used to solve my problem.

Here's the function I used:

public static List<T> GetLogicalChildCollection<T>(object parent) where T : DependencyObject
{
    List<T> logicalCollection = new List<T>();
    GetLogicalChildCollection(parent as DependencyObject, 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);
        }
    }
}

In my code I used these lines to append what I needed to my expanders:

List<Expander> exp = GetLogicalChildCollection<Expander>(printpage.StackPanelPrinting);

foreach (Expander exp in expander)
{
    exp.IsExpanded = true;
    exp.FontWeight = FontWeights.Bold;
    exp.Background = Brushes.LightBlue;
}
Community
  • 1
  • 1
NickGames
  • 312
  • 1
  • 18