How can I make a WPF Expander Stretch?

This solution is a lot simpler and does not effect other expander controls you may using in your application.

  <Expander ExpandDirection="Right" Grid.Column="0" Name="topOfB"> 
    <Expander.Header>
        <Grid HorizontalAlignment="Stretch" Width="{Binding Path=ActualWidth, ElementName=topOfB}">
            <!-- control content goes here -->


Non stretchable Expanders is usually the problem of non stretchable parent controls.. Perhaps one of the parent controls has defined a HorizontalAlignment or VerticalAlignment property?

If you can post some sample code, we can give you a better answer.


All you need to do is this:

<Expander>
  <Expander.Header>
    <TextBlock
      Text="I am header text..."
      Background="Blue"
      Width="{Binding
        RelativeSource={RelativeSource
          Mode=FindAncestor,
          AncestorType={x:Type Expander}},
        Path=ActualWidth}"
      />
  </Expander.Header>
  <TextBlock Background="Red">
    I am some content...
  </TextBlock>
</Expander>

http://joshsmithonwpf.wordpress.com/2007/02/24/stretching-content-in-an-expander-header/


The accepted answer draws outside the control because the header content is in one column and the expander button is in the first. Might be good enough for some cases.

If you want a clean solution you have to change the template of the expander.

Another way is an attached property:

using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
public static class ParentContentPresenter
{
    public static readonly System.Windows.DependencyProperty HorizontalAlignmentProperty = System.Windows.DependencyProperty.RegisterAttached(
        "HorizontalAlignment",
        typeof(HorizontalAlignment),
        typeof(ParentContentPresenter),
        new PropertyMetadata(default(HorizontalAlignment), OnHorizontalAlignmentChanged));

    public static void SetHorizontalAlignment(this UIElement element, HorizontalAlignment value)
    {
        element.SetValue(HorizontalAlignmentProperty, value);
    }

    [AttachedPropertyBrowsableForChildren(IncludeDescendants = false)]
    [AttachedPropertyBrowsableForType(typeof(UIElement))]
    public static HorizontalAlignment GetHorizontalAlignment(this UIElement element)
    {
        return (HorizontalAlignment)element.GetValue(HorizontalAlignmentProperty);
    }

    private static void OnHorizontalAlignmentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var presenter = d.Parents().OfType<ContentPresenter>().FirstOrDefault();
        if (presenter != null)
        {
            presenter.HorizontalAlignment = (HorizontalAlignment) e.NewValue;
        }
    }

    private static IEnumerable<DependencyObject> Parents(this DependencyObject child)
    {
        var parent = VisualTreeHelper.GetParent(child);
        while (parent != null)
        {
            yield return parent;
            child = parent;
            parent = VisualTreeHelper.GetParent(child);
        }
    }
}

It lets you do:

<Expander Header="{Binding ...}">
    <Expander.HeaderTemplate>
        <DataTemplate>
            <!--Using a border here to show how width changes-->
            <Border BorderBrush="Red" BorderThickness="1"
                    local:ParentContentPresenter.HorizontalAlignment="Stretch">
                ...    
            </Border>
        </DataTemplate>
    </Expander.HeaderTemplate>
</Expander>

Note that the use of the attached property is somewhat fragile as it assumes that there is a ContentPresenter in the template.