I realize this question has been asked before, but I'm unable to make do with the minimal code samples. I'm requesting a review on the entire thing.
I have a WPF DataGrid that displays a bunch of rows. Each row has a right-click ContextMenu with its own commands.
I'm not able to get the ContextMenu part right. It's complaining that "ContextMenu cannot have a logical or visual parent." Any help would be appreciated.
Thanks.
XAML File:
<DataGrid ItemsSource="{Binding MyModules}" AutoGenerateColumns="False"> <!-- Begin uncertain part --> <ContextMenu ItemsSource="{Binding Configuration.Commands}"> <ContextMenu.ItemContainerStyle> <Style TargetType="x:Type ContextMenuItem"> <Setter Property="Command" Value="Binding Command}" /> </Style> </ContextMenu.ItemContainerStyle> </ContextMenu> <!-- End uncertain part --> <DataGrid.Columns> <DataGridTemplateColumn Header="Module Name" Width="*" IsReadOnly="True"> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <TextBlock Text="{Binding Configuration.Name}" /> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> <DataGridTemplateColumn Header="Module Description" Width="3*" IsReadOnly="True"> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <TextBlock Text="{Binding Configuration.Description}" /> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> </DataGrid.Columns>
ViewModel Files:
public ObservableCollection<IModule> MyModules { get; set; } // ... public interface IModule { Configuration Configuration { get; } void ExecuteCommand(Command command); } public class Configuration { public Guid Id { get; private set; } public string Name { get; private set; } public string Description { get; private set; } public List<Command> Commands = new List<Command>(); public Configuration(string name, string description, List<Command> commands) { Id = new Guid(); Name = name; Description= description; Commands = commands; } }
EDIT 1:
I got samples from a bunch of places. Now it compiles. The right-click context menu is completely empty, however.
<DataGrid ItemsSource="{Binding MyModules}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Configuration Name" Width="*" IsReadOnly="True">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Configuration.Name}">
<TextBlock.ContextMenu>
<ContextMenu ItemsSource="{Binding Configuration.Commands}">
<ContextMenu.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="Command" Value="{Binding ItemAction}" />
<Setter Property="Header" Value="{Binding ItemHeader}" />
</Style>
</ContextMenu.ItemContainerStyle>
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Description" Width="3*" IsReadOnly="True">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Configuration.MainMenuDescription}">
<TextBlock.ContextMenu>
<ContextMenu ItemsSource="{Binding Configuration.Commands}">
<ContextMenu.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="Command" Value="{Binding ItemAction}" />
<Setter Property="Header" Value="{Binding ItemHeader}" />
</Style>
</ContextMenu.ItemContainerStyle>
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
Although I don't really like the second approach. I'm having to duplicate the ContextMenu markup for each column...