Reputation: 523
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...
Upvotes: 0
Views: 883
Reputation: 169420
You could define an ItemContainerStyle
where you set the ContextMenu
property for all rows:
<DataGrid ItemsSource="{Binding MyModules}" AutoGenerateColumns="False">
<DataGrid.ItemContainerStyle>
<Style TargetType="DataGridRow">
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu ItemsSource="{Binding Configuration.Commands}">
<ContextMenu.ItemContainerStyle>
<Style TargetType="{x:Type ContextMenuItem}">
<Setter Property="Command" Value="{Binding Command}" />
</Style>
</ContextMenu.ItemContainerStyle>
</ContextMenu>
</Setter.Value>
</Setter>
</Style>
</DataGrid.ItemContainerStyle>
<DataGrid.Columns>
...
</DataGrid.Columns>
</DataGrid>
Upvotes: 1