by Chad
6. November 2009 12:14
Recently, I wanted to add a custom tooltip to my WPF application. I wanted the tooltip to display some details about a record and provide buttons that could be clicked to perform some actions on that record. It turns out that this is a very simple thing to do, but because I started with the idea of a tooltip it was a difficult road to my final solution. It appears that several others on the internet have experienced the same situation as I did, so I decided to blog about it.
First Attempt
Starting with the ToolTip, I quickly found that as I moused over the rows, my custom tooltip would display with the buttons. When I tried to click a button the tooltip would move to the next record in my list; effectively forcing me to chase the control around the screen. So I thought to myself, let’s try activating the tooltip on a right-click and preventing it from automatically closing. A quick search in my favorite search engine indicated that this was a misuse of the ToolTip control.
<!-- Source Code Reenactment: !!!THIS DOESN’T WORK!!! -->
<TextBlock.ToolTip>
<ToolTip>
<ToolTip.Template>
<ControlTemplate>
<Button>Do Something</Button>
</ControlTemplate>
</ToolTip.Template>
</ToolTip>
</TextBlock.ToolTip>
Solution
With a little research, I found that the functionality that I was looking for came with the ContextMenu and Popup controls. Both appeared that they’d solve my problem. Both allowed me to display content floating outside of the visual tree and both will accept focus. I ultimately decided to use the ContextMenu because it has built-in right-click support and will automatically hide itself when I click outside of it.
<TextBlock.ContextMenu>
<ContextMenu>
<ContextMenu.Template>
<ControlTemplate>
<Border Background="Black" CornerRadius="10">
<Button Margin="5">Do Something</Button>
</Border>
</ControlTemplate>
</ContextMenu.Template>
</ContextMenu>
</TextBlock.ContextMenu>
Now, when I right-click my record, a context menu (that doesn’t look like your traditional context menu) displays. I can fully interact with any controls in my ControlTemplate. When a button (with an event handler) is clicked or when I click outside of the ContextMenu, the menu hides itself. Exactly what I wanted.
I hope that this saves someone some time!