How do I dynamically bind and statically add MenuItems?

18,389

You can use a CompositeCollection to do this, you can combine different Collections and add static items in the xaml.

Example:

Xaml:

<Window x:Class="WpfApplication8.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="233" Width="143" Name="UI">
    <Window.Resources>
        <CollectionViewSource Source="{Binding ElementName=UI, Path=Windows}" x:Key="YourMenuItems"/>
     </Window.Resources>

    <Grid DataContext="{Binding ElementName=UI}">
        <Menu Height="24" VerticalAlignment="Top">
            <MenuItem Header="_View" >
                <MenuItem Header="Windows">
                    <MenuItem.ItemsSource>
                        <CompositeCollection>
                            <CollectionContainer Collection="{Binding Source={StaticResource YourMenuItems}}" />
                            <MenuItem Header="Menu Item 1" />
                            <MenuItem Header="Menu Item 2" />
                            <MenuItem Header="Menu Item 3" />
                        </CompositeCollection>
                    </MenuItem.ItemsSource>
                    <MenuItem.ItemContainerStyle>
                        <Style>
                            <Setter Property="MenuItem.Header" Value="{Binding Title}"/>
                        </Style>
                    </MenuItem.ItemContainerStyle>
                </MenuItem>
            </MenuItem>
        </Menu>
    </Grid>
</Window>

Code

public partial class MainWindow : Window
{
    private ObservableCollection<MyObject> _windows = new ObservableCollection<MyObject>();

    public MainWindow()
    {
        InitializeComponent();
        Windows.Add(new MyObject { Title = "Collection Item 1" });
        Windows.Add(new MyObject { Title = "Collection Item 2" });
    }

    public ObservableCollection<MyObject> Windows
    {
        get { return _windows; }
        set { _windows = value; }
    }
}

public class MyObject
{
    public string Title { get; set; }
}

Result:

enter image description here

Share:
18,389

Related videos on Youtube

webe0316
Author by

webe0316

Merge with http://stackoverflow.com/users/598859/webe0316

Updated on June 19, 2022

Comments

  • webe0316
    webe0316 almost 2 years

    I'm binding the ItemsSource of my MenuItem to an ObservableCollection in my ViewModel. Here is my xaml:

    <MenuItem Header="_View"
              ItemsSource="{Binding Windows}">
      <MenuItem.ItemContainerStyle>
        <Style>
          <Setter Property="MenuItem.Header"
                  Value="{Binding Title}" />
        </Style>
      </MenuItem.ItemContainerStyle>
    </MenuItem>
    

    This part works great, but now I also want to add some static MenuItems to the same View MenuItem, separated with a separator. Something like this, even though I know this won't work because I can't set the items twice.

    <MenuItem Header="_View"
              ItemsSource="{Binding Windows}">
      <MenuItem.ItemContainerStyle>
        <Style>
          <Setter Property="MenuItem.Header"
                  Value="{Binding Title}" />
        </Style>
      </MenuItem.ItemContainerStyle>
      <Separator />
      <MenuItem Header="item 1" />
      <MenuItem Header="item 2" />
    </MenuItem>
    

    For now I have created a work around by adding another level to the MenuItem like this:

    <MenuItem Header="_View">
      <MenuItem Header="Windows"
                ItemsSource="{Binding Windows}">
        <MenuItem.ItemContainerStyle>
          <Style>
            <Setter Property="MenuItem.Header"
                    Value="{Binding Title}" />
          </Style>
        </MenuItem.ItemContainerStyle>
      </MenuItem>
      <MenuItem Header="Load Layout" />
      <MenuItem Header="Save Layout" />
    </MenuItem>
    

    This works fine, but I'd rather not have a sub menu if at all possible. Oh, and I'd also prefer to do this in xaml instead of code behind. Any ideas?

    • Federico Berasategui
      Federico Berasategui over 11 years
      Maybe you can use CompositeCollection to "unify" your collection from the VM with your XAML defined collection.
  • Pyritie
    Pyritie over 7 years
    What is the {Binding ElementName=UI} stuff for?
  • JobaDiniz
    JobaDiniz over 7 years
    what if I'm data binding Menu ItemsSource (not one of its MenuItems)? I couldn't get the ItemContainerStyle to work, because I set Menu.ItemContainerStyle and that's wrong...