0
votes

I am creating a WPF application for reading logs. Currently, I have Expanders inside of Expanders. When I click on an Expander, I want the scope to be the contents of that Expander. All other peer Expanders disappear (Visibility.Collapsed).

This works for the first line of Expanders. Once I expand a child Expander, this works again, but the parent Expander is still listed above it.

I'd like to collapse peers (same as before) as well as the parent, but keep the parent expanded, so that just the expanded child is showing by itself.

That was a lot of "expand" in a few sentences! But anyways ...

Here's an example of what expected output:

Initially:

  • Expander 1

  • Expander 2

  • Expander 3

  • Expander 4

Let's say I click Expander 2:

  • Expander 2

    1. Child Expander 1

    2. Child Expander 2

    3. Child Expander 3

    4. Child Expander 4

All others are collapsed, but still expanded. Children are displayed.

Let's say I click Child Expander 3

  1. Child Expander 3

All others are collapsed, including the parent!

Is there a way to accomplish this?

Here's my current code (Toggling is kindof confusing at first):

private Boolean toggleLogs = false;
private Boolean subToggleLogs = false;
public LogsControl()
{
    InitializeComponent();
}

private void expanderPanel_Click(object sender, RoutedEventArgs e)
{
    toggleLogs = !toggleLogs;
    if (toggleLogs == true)
    {
        setLogVisibility(expanderPanel);
    } else
    {
        toggleLogVisibility(expanderPanel);
    }
}

private void windowsServicePanel_Click(object sender, RoutedEventArgs e)
{
    toggleLogs = false;
    subToggleLogs = !subToggleLogs;
    if (subToggleLogs == true)
    {
        setLogVisibility(windowsServicePanel);
    }
    else
    {
        toggleLogVisibility(windowsServicePanel);
    }
}

private void javaPanel_Click(object sender, RoutedEventArgs e)
{
    toggleLogs = false;
    subToggleLogs = !subToggleLogs;
    if (subToggleLogs == true)
    {
        setLogVisibility(javaPanel);
    }
    else
    {
        toggleLogVisibility(javaPanel);
    }
}

public void toggleLogVisibility(StackPanel panel)
{
    var childNumber = VisualTreeHelper.GetChildrenCount(panel);

    for (var i = 0; i <= childNumber - 1; i++)
    {
        var uiElement = VisualTreeHelper.GetChild(panel, i) as Expander;

        uiElement.Foreground = new SolidColorBrush(Colors.White);

        if (uiElement.IsExpanded == false)
        {
            uiElement.Visibility = Visibility.Visible;
        }
    }
}

public void setLogVisibility(StackPanel panel)
{
    var childNumber = VisualTreeHelper.GetChildrenCount(panel);

    for (var i = 0; i <= childNumber - 1; i++)
    {
        var uiElement = VisualTreeHelper.GetChild(panel, i) as Expander;

        if (uiElement.IsExpanded == true)
        {
            uiElement.Foreground = (SolidColorBrush)(new BrushConverter().ConvertFrom("#FF3399FF"));
            uiElement.Visibility = Visibility.Visible;
        }
        else
        {
            uiElement.Visibility = Visibility.Collapsed;
        }
    }
}
1

1 Answers

2
votes

If you set a controls visibility to collapsed or hidden, all child controls and content is collapsed / hidden. No way around that. You'd have to simulate the hierarchy if you want to do what you want. Instead of actually nesting the expanders, just make it look like it on the screen, but you'll have difficulty keeping all the visibility states in sync that way.