JokerMartini
JokerMartini

Reputation: 6147

wpf - Header of Expander fit contents width?

Is there any way to make the Header of an Expander Fit the max-width in a resizeable window in WPF? It appears that no matter what I do I can't get the contents to expand to maximum width. It does work in the Content section of the Expander.

enter image description here

<Grid Background="LightGray">

    <Expander IsExpanded="True">
         <Expander.Header>
              <Grid Width="100" Height="50">
                   <Rectangle Fill="Red"></Rectangle>
              </Grid>
         </Expander.Header>

         <Rectangle Fill="Red"></Rectangle>

    </Expander>

</Grid>

Upvotes: 2

Views: 3008

Answers (2)

Sergii Zhevzhyk
Sergii Zhevzhyk

Reputation: 4202

The fastest way is to bind the width of the header to the width of the whole expander.

<Expander IsExpanded="True">
  <Expander.Header>
      <Grid Width="{Binding RelativeSource={RelativeSource
            Mode=FindAncestor,
            AncestorType={x:Type Expander}},
            Path=ActualWidth}"
            Height="50">
            <Rectangle Fill="Red"></Rectangle>
      </Grid>
  </Expander.Header>
  <Rectangle Fill="Red"></Rectangle>
</Expander>

But it's not a precise method because you have the arrow which also takes some space and you can see that the header is a bit wider than you need. Changed width for expander's header

You can override the standard template (HeaderTemplate) of the expander's header.

UPDATE

I found a possible solution using the code-behind file (all credits go to @kmatyaszek).

Add a helper class to find the control we need to change the width. It checks the whole Visual Tree of the parent control and returns a child of the type we are looking for.

public static class VTHelper
{
    public static T FindChild<T>(DependencyObject parent) where T : DependencyObject
    {
        if (parent == null) return null;

        T childElement = null; 
        int childrenCount = VisualTreeHelper.GetChildrenCount(parent); 
        for (int i = 0; i < childrenCount; i++)
        {
            var child = VisualTreeHelper.GetChild(parent, i);
            T childType = child as T; 
            if (childType == null)
            {
                childElement = FindChild<T>(child); 
                if (childElement != null) 
                    break;
            }
            else
            {
                childElement = (T)child; 
                break;
            }
        } 
        return childElement;
    }
}

Add a handler to process the loading event. It changes the HorizontalAlignment property of the ContentPresenter instance:

private void expander_Loaded(object sender, RoutedEventArgs e)
{
    var tmp = VTHelper.FindChild<ContentPresenter>(sender as Expander);
    if (tmp != null)
    {
        tmp.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
    }
}

Attach this handler to the expander:

<Expander IsExpanded="True" Loaded="expander_Loaded">

This approach uses the code-behind but it doesn't work with any data (or ViewModel). It changes only the visual appearance of the control.

Upvotes: 7

Mubarack Ali
Mubarack Ali

Reputation: 45

        <Expander Name="myexpander" IsExpanded="True" Margin="0,0,1,0">
            <Expander.Header>
                <Grid Width="{Binding ElementName=myexpander, Path=ActualWidth}" Height="50">
                    <Rectangle Fill="Red"></Rectangle>
                </Grid>
            </Expander.Header>

            <Rectangle Fill="Red"></Rectangle>

        </Expander>

    </Grid>

give a name to your expander and bind the width property

Upvotes: 3

Related Questions