OsQu
OsQu

Reputation: 1058

WPF Displaying context menu for GridView's column header when left clicking

I want to display a context menu when a user left clicks a GridView's column header. Here's my code so far:

<GridView>
    <GridViewColumn DisplayMemberBinding="{Binding}">
        <GridViewColumnHeader
            Content="Customer"
            Click="Header_Click"
            >
            <GridViewColumnHeader.ContextMenu>
                <ContextMenu Name="ContextMenu">
                    <MenuItem Header="Sort by Customer" />
                    <MenuItem Header="Sort by Address" />
                </ContextMenu>
            </GridViewColumnHeader.ContextMenu>
        </GridViewColumnHeader>
    </GridViewColumn>
</GridView>

And the code behind:

private void Header_Click(object sender, RoutedEventArgs e)
{
    ContextMenu.IsOpen = true;

    e.Handled = true;
}

Note that GridView is hosted by customized ListView class that has an event listener on GridViewColumnHeader.ClickEvent. However when setting e.Handled on code behind's event listener it stops the event from bubbling upwards.

What my problem is that when clicking the header the context menu just quickly appears on screen and closes right after that. I believe that the header is losing its focus somehow and that's why the context menu is closed. Even setting the StaysOpen property to true won't fix the problem.

Also please note that when right clicking the column header the context menu behaves correctly.

So any suggestion how to stop the context menu from closing?

Upvotes: 2

Views: 5996

Answers (1)

xlk
xlk

Reputation: 136

the problem here is that a mouse click causes several events. In your case either the MouseDown or the MouseUp event (or both) perform the default action for clicking on headers (sorting I guess). I was able to reproduce the behaviour which you described. To fix this behaviour you can register the MouseDown and the MouseUp event and trigger the context menu.

<GridView>
    <GridViewColumn DisplayMemberBinding="{Binding Path=Customers}">
        <GridViewColumnHeader
            Content="Customer"
            MouseDown="GridViewColumnHeader_MouseDown" MouseUp="GridViewColumnHeader_MouseDown">
            <GridViewColumnHeader.ContextMenu>
                <ContextMenu Name="TheContextMenu">
                    <MenuItem Header="Sort by Customer" />
                    <MenuItem Header="Sort by Address" />
                </ContextMenu>
            </GridViewColumnHeader.ContextMenu>
        </GridViewColumnHeader>
    </GridViewColumn>
</GridView>

I use GridViewColumnHeader_MouseDown twice which might be a bit dirty :)

private void GridViewColumnHeader_MouseDown(object sender, MouseButtonEventArgs e)
{
    TheContextMenu.IsOpen = true;
    e.Handled = true;
}

Sort of edit: I've just been playing around a bit. It seems like the MouseUp event is sufficient.

Upvotes: 3

Related Questions