VerticalAlignment for ItemsPanel

577 views Asked by At

iv'e got a custom panel which derives from stack panel

this panel has a layout logic which depends on the vertical Alignment of the Panel

CS :

  public class ReArrangeStackPanel : StackPanel
  {      
    protected override Size ArrangeOverride(Size arrangeSize)
    {
        double delta =  this.VerticalAlignment == System.Windows.VerticalAlignment.Bottom 
                              ? CalcForBottom() : CalcForTop();                        

        ChildrenArrangement(delta);

        return base.ArrangeOverride(arrangeSize);
    }

1) i would expect the VerticalAligment Property of the ItemsPanel to be Inherited from the items control which it is a child of , it seems that it does not since it's set with the default "Stretch" Value .

2) Even when explicitly setting VerticalAlignment on the ItemsPanel , if i don't Hard code the value the VerticalAlignment is set to "Stretch" in the ArrangeOverride scope , and only later (which i observe using snoop) is set with the "Bottom" value .

XAML :

a) doesn't work : with binding , the value is set but only after ArrangeOverride.

<Setter Property="ItemsPanel">
        <Setter.Value>
            <ItemsPanelTemplate>
                <local:ReArrangeStackPanel 
                      VerticalAlignment="{Binding Path=VerticalAlignment, 
                      RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:PipeControl}}}" />
            </ItemsPanelTemplate>
        </Setter.Value>
    </Setter>

b) works : Explicitly hard coding the value .

    <ItemsPanelTemplate>
         <local:ReArrangeStackPanel VerticalAlignment="Bottom" />
    </ItemsPanelTemplate>

in my Windows XAML the ItemsControl (PipeControl) is Set with the wanted VerticalAlignment .

so my questions :

1) why is the value not inherited ?

2) why is the value not set via binding before ArrangeOverride occurs ?

thanks in advance .

1

There are 1 answers

0
Rachel On

The default value of FrameworkElement.VerticalAlignment is Stretch, so it makes sense that the default value for your ReArrangeStackPanel.VerticalAlignment class is also Stretch

Since the typical style of sizing for WPF controls is usually based on the parent panel, it's possible that the ArrangeOverride method of a StackPanel is what actually sets the VerticalAlignment property for a StackPanel, and you are overwriting that method.

If this is indeed the case, then you could ensure the default is set correctly by calling base.ArrangeOverride() in your ArrangeOverride() method

protected override Size ArrangeOverride(Size arrangeSize)
{
    base.ArrangeOverride(arrangeSize);

    ...
}

As for why the binding isn't working, I suspect it's because Rendering occurs after DataBinding, so the VerticalAlignment property isn't set until after the parent control you are binding to has been Rendered.

You can verify if this is the case or not by putting a Converter in your VerticalAlignment binding and checking out what the value is when it gets evaluted.