I want to show a list of items in a WPF ListView and use a tooltip to show additional details of an item in the list.
I have made a sample project which you can download from http://www.jollans.com/WpfTooltipTest.zip
For the sample I have made a class with some properties:
class ItemClass
{
public String mainProperty_1 { get; set; }
public String mainProperty_2 { get; set; }
public String detailProperty_1 { get; set; }
public String detailProperty_2 { get; set; }
}
and a model which contains a list of these items
class Model
{
public ObservableCollection<ItemClass> Items { get; private set; }
public Model()
{
Items = new ObservableCollection<ItemClass>() ;
Items.Add ( new ItemClass { mainProperty_1 = "One", mainProperty_2 = "First item", detailProperty_1="A", detailProperty_2 = "1" } ) ;
Items.Add ( new ItemClass { mainProperty_1 = "Two", mainProperty_2 = "Second item", detailProperty_1="B", detailProperty_2 = "2" } ) ;
Items.Add ( new ItemClass { mainProperty_1 = "Three", mainProperty_2 = "Third item", detailProperty_1="C", detailProperty_2 = "3" } ) ;
Items.Add ( new ItemClass { mainProperty_1 = "Four", mainProperty_2 = "Fourth item", detailProperty_1="D", detailProperty_2 = "4" } ) ;
Items.Add ( new ItemClass { mainProperty_1 = "Five", mainProperty_2 = "Fifth item", detailProperty_1="E", detailProperty_2 = "5" } ) ;
Items.Add ( new ItemClass { mainProperty_1 = "six", mainProperty_2 = "Sixth item", detailProperty_1="F", detailProperty_2 = "6" } ) ;
}
}
The main window just instantiates the model and sets it as the DataContext
public partial class MainWindow : Window
{
private Model _model ;
public MainWindow()
{
InitializeComponent();
_model = new Model() ;
this.DataContext = _model ;
}
}
The basic ListView is something like this:
<ListView ItemsSource="{Binding Items}">
<ListView.View>
<GridView>
<GridViewColumn Width="100" Header="Main Property 1" DisplayMemberBinding="{Binding Path=mainProperty_1}"/>
<GridViewColumn Width="200" Header="Main Property 2" DisplayMemberBinding="{Binding Path=mainProperty_2}"/>
</GridView>
</ListView.View>
</ListView>
but this doesn't have any tooltips.
I know that one way is to add something like:
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="ToolTip" Value="{Binding Path=detailProperty_1}" />
</Style>
</ListView.ItemContainerStyle>
which shows a single property from the ItemClass, but I want something much more elaborate.
I have defined a style resource containing a grid as a tooltip:
<Window.Resources>
<Style x:Key="ItemTooltip" TargetType="ToolTip">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Grid Margin="5">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="113"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0">Main property 1:</TextBlock>
<TextBlock Grid.Row="1" Grid.Column="0">Main property 2:</TextBlock>
<TextBlock Grid.Row="2" Grid.Column="0">Detail property 1:</TextBlock>
<TextBlock Grid.Row="3" Grid.Column="0">Detail property 2:</TextBlock>
<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Path=mainProperty_1}" />
<TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Path=mainProperty_2}" />
<TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding Path=detailProperty_1}" />
<TextBlock Grid.Row="3" Grid.Column="1" Text="{Binding Path=detailProperty_2}" />
</Grid>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
I have added a third column to the grid with a TextBlock, which uses this tooltip.
<ListView ItemsSource="{Binding Items}">
<ListView.View>
<GridView>
<GridViewColumn Width="100" Header="Main Property 1" DisplayMemberBinding="{Binding Path=mainProperty_1}"/>
<GridViewColumn Width="200" Header="Main Property 2" DisplayMemberBinding="{Binding Path=mainProperty_2}"/>
<GridViewColumn Width="200" Header="Main Property 2 again" >
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=mainProperty_2}">
<TextBlock.ToolTip>
<ToolTip Style="{StaticResource ItemTooltip}" DataContext="{Binding}" />
</TextBlock.ToolTip>
</TextBlock>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
(I don't really want the TextBlock, but that is not the subject of this question.)
The tooltip is displayed and shows the grid, but the bindings don't work, because I haven't set up the DataContext. I have defined four rows in the grid which should display fields from the ItemClass.
How can I set up the DataContext in the tooltip, so that I can bind to properties of the item in the grid where the tooltip is shown?
The ToolTip property is an object, so you can just use Setter.Value syntax:
<Setter Property="ToolTip">
<Setter.Value>
<Grid...>
</Grid>
</Setter.Value>
</Setter>
The tooltip will be rendered via a ContentPresenter, so anything in there will show correctly.