views:

869

answers:

1

In Silverlight 3, I am trying to create a pop up menu for navigation. I am using a HyperlinkButton as a trigger, which when moused over displays a Popup containing more HyperlinkButtons. The root node is right aligned and I want the sub-menu to appear to the left. My problem is that I am trying to position the popup using its ActualWidth property, but this value appears fixed at the size of the root element (which contains the trigger and the popup), so if the popup is narrower it leaves an unsightly gap and if wider it overwrites the trigger.

Here is my XAML:

<Grid x:Name="LayoutRoot" Background="White">
    <Grid.Resources>
        <Style x:Key="MenuItemStyle" TargetType="HyperlinkButton">
            <Setter Property="Background" Value="Blue" />
            <Setter Property="Foreground" Value="White" />
            <Setter Property="HorizontalContentAlignment" Value="Center" />
        </Style>
    </Grid.Resources>

    <Grid x:Name="Root" HorizontalAlignment="Right" VerticalAlignment="Top">
        <HyperlinkButton 
            x:Name="hl"  
            Style="{StaticResource MenuItemStyle}"
            MouseEnter="hl_MouseEnter" MouseLeave="hl_MouseLeave">
            <HyperlinkButton.Content>
                <Grid>
                    <TextBlock Text="MenuRoot" />
                </Grid>
            </HyperlinkButton.Content>
        </HyperlinkButton>

        <Popup x:Name="p">
            <Popup.Child>
                <HyperlinkButton 
                    Style="{StaticResource MenuItemStyle}">
                    <HyperlinkButton.Content>
                        <StackPanel>
                            <TextBlock Text="Sub" />
                        </StackPanel>
                    </HyperlinkButton.Content>
                </HyperlinkButton>
            </Popup.Child>
        </Popup>
    </Grid>
</Grid>

and my code:

    private void hl_MouseEnter(object sender, MouseEventArgs e)
    {
        p.HorizontalOffset = -p.ActualWidth;
        p.IsOpen = true;
    }

    private void hl_MouseLeave(object sender, MouseEventArgs e)
    {
        p.IsOpen = false;
    }

I have tried using the popup's child's width, but this is set to 0 during the MouseEnter event, because it is hidden.

I'm new to Silverlight so any help would be appreciated.

+1  A: 

The Popup expands to fill the grid column, but the contents of the Popup isn't actually measured and positioned until after the Popup has been displayed. You can work around this by naming the contents of the Hyperlink. Assume that the inner Hyperlink is named s. Then you can modify your event handler to this:

private void hl_MouseEnter(object sender, MouseEventArgs e)
{
  p.IsOpen = true;
  p.UpdateLayout();
  p.HorizontalOffset = -s.ActualWidth;
}

After the call to UpdateLayout the inner Hyperlink has it's natural size.

Unfortunately, the Popup closes as soon as the mouse leave the parent Hyperlink making it impossible to click the child Hyperlink.

Martin Liversage
I can work around that issue. I didn't know about UpdateLayout, many thanks!
CodeMonkey1