1

I'm trying to have a dynamic menu item using MVVM from an observable collection. Everything worked, but then I needed to add a "add new" button to the end. I found a solution using a CompositeCollection, like here:

How do I dynamically bind and statically add MenuItems?

So have the following code, where TimeSpans is a collection of ViewModels:

    <MenuItem Header="Time Ranges">
        <MenuItem.ItemsSource>
            <CompositeCollection>
                <CollectionContainer Collection="{Binding TimeSpans}" />
                <Separator />
                <MenuItem Header="Add New" cal:Message.Attach="NewTimeSpan()" />
            </CompositeCollection>
        </MenuItem.ItemsSource>
        <MenuItem.ItemTemplate>
            <ItemContainerTemplate>
                <MenuItem Header="{Binding Name}" cal:Message.Attach="ConfigureTimeSpan()" />
            </ItemContainerTemplate>
        </MenuItem.ItemTemplate>
    </MenuItem>

However, the view models are not populated like it was just using ItemsSource="{Binding TimeSpans}", it's not showing anything:

enter image description here

I suspect this is because I'm in the StackOverflow answer above the binding is actually a collection of MenuItems, so that composite collection makes sense. Whereas mine's mixing ViewModels & MenuItems.

Is there any way to construct the collection of menu-items created from ViewModels in the XAML so I can bind it?

Community
  • 1
  • 1
Joe
  • 6,773
  • 2
  • 47
  • 81
  • 1
    Have you tried this? ``. Just like in the linked answer, use a resource. As far as I remember you need that for `CompositeCollection`. – Szabolcs Dézsi Feb 28 '16 at 21:49
  • Seems to come up with the same result. I'll update the xaml in the question though, as you're right I completely missed that in the other answer. Thanks. – Joe Feb 28 '16 at 22:32
  • Ah! Got it. The path needed to be DataContext.TimeSpans, as {Binding TimeSpans} is a short-cut for Caliburn.Micro MVVM framework I'm using. Thanks a lot! – Joe Feb 28 '16 at 22:38

1 Answers1

2

For anyone else who comes across this, as Szabolcs Dezsi said, I needed to use a resource for the CollectionViewSource (bad reading comprehension on my part, as that was in the answer linked in my question).

Working code below:

<MenuItem Header="Time Ranges" x:Name="TimeRangesMenuItem">
    <MenuItem.Resources>
        <CollectionViewSource Source="{Binding ElementName=TimeRangesMenuItem, Path=TimeSpans}" x:Key="TimeSpanMenuItems" />
    </MenuItem.Resources>
    <MenuItem.ItemsSource>
        <CompositeCollection>
            <CollectionContainer Collection="{Binding Source={StaticResource TimeSpanMenuItems}}" />
            <Separator />
            <MenuItem Header="Add New" cal:Message.Attach="NewTimeSpan()" />
        </CompositeCollection>
    </MenuItem.ItemsSource>
    <MenuItem.ItemTemplate>
        <ItemContainerTemplate>
            <MenuItem Header="{Binding Name}" cal:Message.Attach="ConfigureTimeSpan()" />
        </ItemContainerTemplate>
    </MenuItem.ItemTemplate>
</MenuItem>
Joe
  • 6,773
  • 2
  • 47
  • 81