How to Stretch a Menu Control to the Width of a Window in WPF

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).


	
	
	
	

A Menu in WPF only stretches to the width of its children by default.

This is contrary to the default behavior of a Toolbar control, which will automatically stretch to the width of its parent container.


	

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:

Width="{Binding ElementName=grid_Main,Path=ActualWidth}"

Which in my application looks like this:


	
		
	

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:


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.

private void menu_Main_Loaded(object sender, RoutedEventArgs e)
{
	this.menu_Main.Width = this.grid_Main.ActualWidth;
}

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:




And in the SizeChanged event, once again set the width of the Menu to the width of its parent container as we did before.

private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
{
	this.menu_Main.Width = this.grid_Main.ActualWidth;
}

This will give you the same functionality as the WPF solution, although it requires some additional code.

How to Create a HTML-style ComboBox in WPF and C#

Before I started doing software development in C# and WPF, I spent quite a bit of time with HTML. Because of this, I was used to having the ability to create drop-down boxes (known as select in HTML) to display lists of information with a “front-end” value the user could see and a “back-end” value that held data.

For example, I could create a list of colors that would display the color’s name in the select box, but would then correspond to a hexadecimal value in the background:




Which looks like:

If the user selected “Green”, it would show up as “#008000” behind the scenes.

This type of control is known as a ComboBox in WPF and C# and has similar functionality, but by default you can’t store Name –> Value pairs in them like you can in HTML. In this guide, I’ll show you some simple code you can use to recreate this functionality.

Creating HTML-style ComboBox in WPF and C#

For this example, I wanted to create a drop-down menu for selecting the Parity value of a serial port connection. Parity is an enumeration in C# and has values like Parity.None, Parity.Even, and Parity.Odd, but I wanted to display just “None”, “Even”, and “Odd” to the user.

The first thing I did was to create a custom class that expands the functionality of the standard ComboBoxItem. This class will store the pretty front-facing name in a string called “contents” and store the data value in an object called “tag”.

If you’re familiar with ComboBoxItems, you’ll know that they already offer Content and Tag properties. These properties don’t function the same way they do in HTML, so I found it best to create my own custom class.


// Contains the visible "Name" of the item.
private string _contents;
public string contents { get { return _contents; } set { _contents = value; } }

// Contains the hidden "Value" of the item.
private object _tag;
public object tag { get { return _tag; } set { _tag = value; } }

public CustomComboBoxItem(string contents, object tag)
{
 this._contents = contents;
 this._tag = tag;
}

// Only the Name will be displayed when the string value is used
public override string ToString() { return _contents; }

I created my ComboBox in WPF and created a Loaded event to programmatically populate the values.




And then created the corresponding comboBox_Parity_Loaded function in my C#  file where I added the CustomComboBoxItem items to the ComboBox. You can see that the first value I give it is its front-facing name, and the second is the value of the Parity enumeration.


private void comboBox_Parity_Loaded(object sender, RoutedEventArgs e)
{
 // Add the options with my custom class CustomComboBoxItem. This allows me to store a unique "Name"=content and "Value"=tag for each item
 comboBox_Parity.Items.Add(new CustomComboBoxItem("None", "Parity.None"));
 comboBox_Parity.Items.Add(new CustomComboBoxItem("Even", "Parity.Even"));
 comboBox_Parity.Items.Add(new CustomComboBoxItem("Odd", "Parity.Odd"));
 comboBox_Parity.Items.Add(new CustomComboBoxItem("Mark", "Parity.Mark"));
 comboBox_Parity.Items.Add(new CustomComboBoxItem("Space", "Parity.Space"));
}

Compiling and executing this program shows my ComboBox filled with items called “None”, “Even”, and “Odd”, but its selected value now corresponds with “Parity.None”, “Parity.Even”, and “Parity.Odd”.

To access the back-end value of the user’s selection in your code (I was using it to change a hardware setting), you need to cast the SelectedItem property of the ComboBox as a CustomComboBoxItem.

// This takes whatever item is selected in the comboBox and stores it in a new item called item_Parity. This gives you access
 // to the properties of the CustomComboBoxItem like .tag and .content.

CustomComboBoxItem item_Parity = (CustomComboBoxItem)this.comboBox_Parity.SelectedItem;

To test it out, you can use the following code to write the item’s name and corresponding value to the console.


Console.WriteLine("Item's name is: " + item_Parity.contents + " and Item's value is: " + item_Parity.tag.ToString());

That’s it! You should now have HTML-style ComboBoxes in WPF and C#.