Click here to Skip to main content
15,881,139 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
Hi,
I need a trick about CONTEXTMENU in a HierarchicalDataTemplate....
I've a HierarchicalDataTemplate like this:
<TreeView ItemsSource="{Binding viewModels}">
    <TreeView.ItemContainerStyle>
        <!-- This Style binds a TreeViewItem to a TreeViewItemViewModel. -->
        <Style TargetType="{x:Type TreeViewItem}">
            <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
            <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
            <Setter Property="FontWeight" Value="Normal" />
        </Style>
    </TreeView.ItemContainerStyle>
    <TreeView.Resources>
        <HierarchicalDataTemplate DataType="{x:Type local:custRootViewModel}" ItemsSource="{Binding Path=Children}">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding Path=name}">
                <TextBlock.ContextMenu>
                    <ContextMenu>
                        <!--- a lot of MenuItem -->
                    </ContextMenu>
                </TextBlock.ContextMenu>
                </TextBlock>
            </StackPanel>
        </HierarchicalDataTemplate>
    </TreeView.Resources>
</TreeView>


I need a specific ContextMenu associate with a node in Treeview...
but I can't Binding ContextMenu.
In a custRootViewModel Class I've two property:
Children: who tell me about children (THIS WORK!)
Actions: who tell me about menuitem (I don't know how to bindin them...)


How can I build ContextMenu?
Thanks...
Posted

1 solution

I didn't quite understand your question, but let's see if I got it right. You need to add content to the ContextMenu of the item based on the actions on the ViewModel, right?
Since the ContextMenu extends from MenuBase that extends from ItemsControl, you can add itens dynamically to it by using the ItemsSourceProperty (which is a DependencyProperty, so accept Bindings) so the ContextMenu you add a ItemsSource="{Binding ContextMenuItems}" and the ContextMenuItems property should be a collection of a new Type that contains the text that should be writen in the MenuItem of the ContextMenu and the ICommand that will be executed by it like:

C#
public class Item : INotifyPropertyChanged
{
    public ICommand Command
    {
        get;
        private set;
    }

    private string _Name;

    public string Name
    {
        get { return _Name; }
        set
        {
            if (_Name != value)
            {
                _Name = value;
                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs("Name"));
            }
        }
    }

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    #endregion
}


Then you need to add to the ContextMenu a DataTemplate for the Item that will be something like:
XML
<ContextMenu.ItemTemplate>
    <DataTemplate>
        <MenuItem Header="{Binding Name}" Command="{Binding Command}"/>
    </DataTemplate>
</ContextMenu.ItemTemplate>


then your Xaml Code will be something like:
XML
<TreeView.Resources>
    <HierarchicalDataTemplate DataType="{x:Type local:custRootViewModel}" ItemsSource="{Binding Path=Children}">
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="{Binding Path=name}">
        <TextBlock.ContextMenu>
            <ContextMenu ItemsSource="{Binding Path=ContextMenuItems}">
                <ContextMenu.ItemTemplate>
                    <DataTemplate>
                        <MenuItem Header="{Binding Name}" Command="{Binding Command}"/>
                    </DataTemplate>
                </ContextMenu.ItemTemplate>
            </ContextMenu>
        </TextBlock.ContextMenu>
            </TextBlock>
        </StackPanel>
    </HierarchicalDataTemplate>
</TreeView.Resources>


Then for each Item in the Children Collection you have a collection of Items for the ContextMenu and using the Command Property you can trigger the action that you need for every specific scenario.

Just for the record you need to add the Command to the CommandBindings (which is a Collection of CommandBinding) of the control for this to work this is done by the use of either the static method CommandManager.RegisterClassCommandBinding(Type typeofthecontrol, new CommandBinding(ICommand command, ExecutedRoutedEventHandler Method, CanExecuteRoutedEventHandler Method)) or by the call of the Add method of the CommandBinding collection (UIElement.CommandBindings).

For further knowledge read:
http://msdn.microsoft.com/en-us/library/system.windows.input.commandbinding.aspx[^]
http://msdn.microsoft.com/en-us/library/system.windows.uielement.commandbindings.aspx[^]
http://msdn.microsoft.com/en-us/library/system.windows.input.commandmanager.registerclasscommandbinding.aspx[^]
http://msdn.microsoft.com/en-us/library/system.windows.controls.contextmenu.aspx[^]

Hope this helps.
All best

Raul Mainardi Neto
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900