Stout
Stout

Reputation: 523

WPF DataGrid: Dynamically-Generated ContextMenu for Individual Rows

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.

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

Answers (1)

mm8
mm8

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

Related Questions