tags:

views:

2144

answers:

2

I want to have some text in an expander header left aligned, then some text right aligned. I have found how to expand the header to the width of the container, and thought I could simply add a dockpanel and set the second text block to Dock Right, but it doesn't seem to help. Any solutions?

<Expander>
  <Expander.Header>
    <DockPanel
      Width="{Binding
        RelativeSource={RelativeSource
        Mode=FindAncestor,
        AncestorType={x:Type Expander}},
        Path=ActualWidth}">
      <TextBlock
        Text="I am header text…"
        Background="LightBlue"
      />
      <TextBlock DockPanel.Dock="Right"
        Text="I am header text…"
        Background="Yellow"
      />
    </DockPanel>
  </Expander.Header>
</Expander>
+1  A: 

Try setting the TextAlignment property to right and the HorizontalAlignment property to stretch on the TextBlocks. That should help i think.

If your use of color is for something other than demo purposes and you literally want the whole element to be right aligned then you might want to look at setting the LastChildFill property of the DockPanel to false.

Stimul8d
That works for what I asked, but, what I really wanted to ask was how to right-align buttons :-)i.e. I want 3 buttons at the right hand side. I tried putting them in a StackPanel with DockPanel.Dock = right and LastChildFill. But that doesn't work. More tips appreciated?
Graeme
Sure,..probably not the best implementation but you could wrap the Buttons in a stackpanel (Orientation=Horizontal) and set the stackpanels HorizontalAlignment to Right. I think that would work.
Stimul8d
Works, sort of. The Rightmost button is only half visible. If I stick a 30 pixel-wide element like a border as the rightmost item in the stackpanel it works. Any idea why the button might be cut off?
Graeme
A: 

Unfortunately, this has to do with an issue with the default expander template, which sets the horizontal alignment of the header to left instead of stretch. The best way to get it working would be to create a new template that sets this correctly. Here's a link for more info:

http://silverlight.net/forums/p/57142/145801.aspx#145801

it's for silverlight, but applies to wpf as well. Another way to do this would be to bind your dockpanel width above to the actual width of the element containing the expander. This isn't a great solution but it works. You'll need to create a value converter for the width. Here's some code:

[ValueConversion(typeof(double), typeof(double))]
public class OffsetDoubleConverter : IValueConverter
{
    #region IValueConverter Members

    public double Offset { get; set; }
    public bool KeepPositive { get; set; }

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        double number = (double)value + Offset;
        if ((KeepPositive) && (number < 0.0))
        {
            number = 0.0;
        }
        return number;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        double number = (double)value - Offset;
        if ((KeepPositive) && (number < 0.0))
        {
            number = 0.0;
        }
        return number;
    }

    #endregion
}

And in your xaml:

<!-- create a ref to your namespace -->
xmlns:loc="clr-namespace:YourNamespace"

...

<Window.Resources>
<loc:OffsetDoubleConverter x:Key="ExpanderConverter" Offset="-208.0" KeepPositive="True"/>
</Window.Resources>

...

<DockPanel Width="{Binding ElementName=ADifferentElement, Path=ActualWidth,
                   Converter={StaticResource ExpanderConverter}}">
...

Again, this isn't the best solution, but it should work. One thing to note, if you set the offset value too small and bind it to a parent of your expander, you can get visual studio to hang since the actualwidth of the parent would be based on your width of the expander.

Let me know if this implementation isn't quite clear. Again, I would really recommend just using a custom template for the expander. You can get the default template and just slightly modify it to make it work. I can post that as well if you'd like.

Mark Synowiec
Thanks. Looks like changing the expander template is the recognised solution:http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/a8e0d080-1f9b-440c-af9c-9885917ac577/
Graeme
It can be easier to bind the HorizontalAlignment of the ContentTemplate using OneWayToSource instead of retemplating the entire Expander.... HorizontalAlignment="{Binding Path=HorizontalAlignment, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContentPresenter}}, Mode=OneWayToSource}"
emddudley