Reputation: 13839
I have a ViewModel (AbstractContextMenu) that represents my context menu (IContextMenu), and I bind a real ContextMenu to it with a DataTemplate:
<DataTemplate DataType="{x:Type local:AbstractContextMenu}">
<ContextMenu x:Name="contextMenu"
ItemsSource="{Binding Path=(local:IContextMenu.Items)}"
IsEnabled="{Binding Path=(local:IContextMenu.IsEnabled)}"/>
</DataTemplate>
Then I have a dummy ConcreteContextMenu for testing that just inherits from AbstractContextMenu. AbstractContextMenu just implements this interface:
public interface IContextMenu : IExtension
{
IEnumerable<IMenuItem> Items { get; set; }
bool IsEnabled { get; set; }
}
I'm using it as a property of another ViewModel object:
public IContextMenu ContextMenu
{
get
{
return m_ContextMenu;
}
protected set
{
if (m_ContextMenu != value)
{
m_ContextMenu = value;
NotifyPropertyChanged(m_ContextMenuArgs);
}
}
}
private IContextMenu m_ContextMenu = new ConcreteContextMenu();
static readonly PropertyChangedEventArgs m_ContextMenuArgs =
NotifyPropertyChangedHelper.CreateArgs<AbstractSolutionItem>(o => o.ContextMenu);
Then I bind a StackPanel to that ViewModel and bind the ContextMenu property on the StackPanel to the ContextMenu property of the ViewModel:
<StackPanel Orientation="Horizontal"
ContextMenu="{Binding Path=(local:AbstractSolutionItem.ContextMenu)}"
ContextMenuOpening="stackPanel_ContextMenuOpening">
<!-- stuff goes in here -->
</StackPanel>
When I run this, the ContextMenuOpening event on the StackPanel is fired, but the ContextMenu is never displayed. I'm not sure if I can even do this (apply a ContextMenu to a ContextMenu ViewModel using a DataTemplate). Anyone know?
Upvotes: 2
Views: 763
Reputation: 1030
Bind the ContextMenu property of your view (StackPanel in this scenario) to the ContextMenu property of your ViewModel and provide a IValueConverter to the binding that will create the ContextMenu object and set the IContextMenu to it's DataContext.
Upvotes: 0
Reputation: 14589
Could you shed some light on the syntax used in the ItemsSource
property in the DataTemplate
? Using parentheses usually means an attached property. And Items
does not seem to be an attached property defined by IContextMenu
(as an interface cannot define such a property).
The DataTemplate is linked to an object of type AbstractContextMenu
which has a property called Items
. So, the DataTemplate could simply reference it like this:
<DataTemplate DataType="{x:Type local:AbstractContextMenu}">
<ContextMenu x:Name="contextMenu"
ItemsSource="{Binding Path=Items)}"
IsEnabled="{Binding Path=IsEnabled}"/>
</DataTemplate>
If the AbstractSolutionItem
class is the VM of the StackPanel
, you could bind it like this:
<StackPanel Orientation="Horizontal"
ContextMenu="{Binding Path=ContextMenu}"
ContextMenuOpening="stackPanel_ContextMenuOpening">
<!-- stuff goes in here -->
</StackPanel>
Of course, the DataTemplate must be "accessible" from the StackPanel.
Upvotes: 0
Reputation: 30418
What is the type of AbstractSolutionItem.ContextMenu
? If it corresponds to the ContextMenu
property in your question, then the problem could be that the type is wrong. The ContextMenu
property of FrameworkElement
is expecting an actual ContextMenu
, not an IContextMenu
. Try checking the output window while debugging your app - you might get an error message stating that this is the problem.
Instead of using a DataTemplate
to define your ContextMenu
, just put the contents of the template StackPanel.ContextMenu
:
<StackPanel Orientation="Horizontal"
ContextMenu="{Binding Path=(local:AbstractSolutionItem.ContextMenu)}"
ContextMenuOpening="stackPanel_ContextMenuOpening">
<StackPanel.ContextMenu DataContext="{Binding Path=(local:AbstractSolutionItem.ContextMenu)}">
<ContextMenu x:Name="contextMenu"
ItemsSource="{Binding Path=Items}"
IsEnabled="{Binding Path=IsEnabled}"/>
</StackPanel.ContextMenu>
<!-- stuff goes in here -->
</StackPanel>
That should get you most of the way there. However, there is still a problem since the ContextMenu
does not know how to create a MenuItem
from an IMenuItem
. To solve this, create an ItemTemplate
for the ContextMenu
, which binds members of IMenuItem
to `MenuItem.
Upvotes: 1