如何从Code Behind展开XAML中的子菜单?
Hey there! Let's work through how to expand that submenu from your code-behind. From the menu structure shown in your image (a parent menu item with nested submenus), here are practical ways to achieve this in WPF:
1. Directly Set IsSubmenuOpen (Simplest Approach)
If you've named your target submenu MenuItem in XAML, this is the quickest way. First, here's an example of what your XAML might look like:
<Menu x:Name="MainApplicationMenu"> <MenuItem Header="File"> <MenuItem x:Name="OpenSubMenu" Header="Open"> <MenuItem Header="Recent Documents"/> <MenuItem Header="Browse Location"/> </MenuItem> <MenuItem Header="Save"/> </MenuItem> </Menu>
Then in your code-behind, just set the IsSubmenuOpen property to true when you want to expand it (like on window load, or a button click):
private void Window_Loaded(object sender, RoutedEventArgs e) { // This will expand the "Open" submenu immediately OpenSubMenu.IsSubmenuOpen = true; // Optional: Ensure the parent "File" menu is also expanded (MainApplicationMenu.Items[0] as MenuItem).IsSubmenuOpen = true; }
2. Dynamically Locate and Expand the Submenu
If your submenu isn't named, or you need to find it dynamically (e.g., for generated menus), you can traverse the menu's item hierarchy:
private void ExpandTargetSubmenu() { // First find the parent menu item (e.g., "File") var parentMenuItem = MainApplicationMenu.Items .OfType<MenuItem>() .FirstOrDefault(item => item.Header.ToString() == "File"); if (parentMenuItem != null) { // Then find the target submenu (e.g., "Open") var targetSubmenu = parentMenuItem.Items .OfType<MenuItem>() .FirstOrDefault(subItem => subItem.Header.ToString() == "Open"); if (targetSubmenu != null) { parentMenuItem.IsSubmenuOpen = true; // Expand parent first targetSubmenu.IsSubmenuOpen = true; // Expand the submenu } } }
Call this method whenever you need to trigger the expansion (e.g., in a button click event).
3. MVVM-Friendly Approach (No Direct Code-Behind Control Access)
If you're using the MVVM pattern, it's better to bind the IsSubmenuOpen property to a view model property instead of manipulating controls directly:
Update Your XAML:
<MenuItem Header="Open" IsSubmenuOpen="{Binding IsOpenSubmenu}"> <MenuItem Header="Recent Documents"/> <MenuItem Header="Browse Location"/> </MenuItem>
Add Property to Your ViewModel:
Make sure your view model implements INotifyPropertyChanged:
public class MainViewModel : INotifyPropertyChanged { private bool _isOpenSubmenu; public bool IsOpenSubmenu { get => _isOpenSubmenu; set { _isOpenSubmenu = value; OnPropertyChanged(nameof(IsOpenSubmenu)); } } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
Then, whenever you want to expand the submenu, just set IsOpenSubmenu = true in your view model.
Quick Notes:
- Always wait until the control is loaded before manipulating it (use the
Loadedevent instead of the window constructor, since controls aren't initialized yet in the constructor). - For dynamically generated menus, ensure all menu items are created before you attempt to traverse and expand them.
内容的提问来源于stack exchange,提问作者user9415363

