If you’ve ever created a Menu in WPF, you’ve probably noticed something peculiar: A Menu will not stretch to fill the entire width of its parent container. If you set the Menu’s width to ‘auto’ or delete the width property altogether, the Menu will shrink to the maximum width needed by its MenuItem elements (so if you have 0 MenuItems, it will disappear completely).
[code lang=”xml”]
<Menu Name="menu_Main" >
<MenuItem Header="_File" />
<MenuItem Header="_Edit" />
<MenuItem Header="_Tools" />
<MenuItem Header="_Help" />
</Menu>
[/code]
This is contrary to the default behavior of a Toolbar control, which will automatically stretch to the width of its parent container.
[code lang=”xml”]
<ToolBar Name="toolbar_Main">
<Button Name="button_File" Content="File" Margin="0,0,3,0" />
<Button Name="button_Edit" Content="Edit" Margin="0,0,3,0" />
<Button Name="button_Tools" Content="Tools" Margin="0,0,3,0" />
<Button Name="button_Help" Content="Help" Margin="0,0,3,0" />
</ToolBar>
[/code]
The easiest solution I’ve found to deal with this problem is to manually bind the width of the Menu to its parent container’s width. To do this, you’ll first need to give the Menu’s parent container a name (I’m using a Grid as the parent, so I called it “grid_Main”) and then add the following code to your Menu:
[code lang=”xml”]
Width="{Binding ElementName=grid_Main,Path=ActualWidth}"
[/code]
Which in my application looks like this:
[code lang=”xml”]
<Grid Name="grid_Main">
<Menu Name="menu_Main" Width="{Binding ElementName=grid_Main,Path=ActualWidth}" >
<!– Menu Contents –>
</Menu>
</Grid>
[/code]
This will stretch your menu to the full length of its parent container, which in my case is the entire window.
If you prefer to do this programatically in C#, you can set the Menu’s width to equal the parent container’s width after the parent container has loaded (doing so before the parent container has loaded would set the Menu’s width to 0).
To do this, I created a Loaded event in my Menu in WPF:
[code lang=”xml”]
<Menu Name="menu_Main" Loaded="menu_Main_Loaded" />
[/code]
And in the event, I set the Menu’s width to the ActualWidth property of its parent container, which is the same Grid I used in the earlier example.
[code lang=”c-sharp”]
private void menu_Main_Loaded(object sender, RoutedEventArgs e)
{
this.menu_Main.Width = this.grid_Main.ActualWidth;
}
[/code]
This has the same effect as binding the element properties in WPF, but we’ve overlooked one important thing: since the width of the Menu is only set when the control is loaded, it will not change if you resize the Window after the application is running.
To deal with this, I found it easiest to create a SizeChanged event on the main Window:
[code lang=”xml”]
<Window Title="MainWindow" SizeChanged="Window_SizeChanged">
<!– Window contents –>
</Window>
[/code]
And in the SizeChanged event, once again set the width of the Menu to the width of its parent container as we did before.
[code lang=”c-sharp”]
private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
{
this.menu_Main.Width = this.grid_Main.ActualWidth;
}
[/code]
This will give you the same functionality as the WPF solution, although it requires some additional code.
Leave a Reply
You must be logged in to post a comment.