WPF Show data from multiple DataContexts in ToolTip of ItemsControl

data-binding, datacontext, itemscontrol, tooltip, wpf

Solution

After an hour of hair pulling I have come to the conviction that you can't reference another DataContext inside a DataTemplate for a ToolTip. For other Bindings it is perfectly possible as other posters have proven. That's why you can't use the RelativeSource trick either. What you can do is implement a static property on your Item class and reference that:

<Window x:Class="ToolTipSpike.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300"
    Name="Root"
    xmlns:ToolTipSpike="clr-namespace:ToolTipSpike">
    <Grid>
        <ItemsControl x:Name="itemsControl" ItemsSource="{Binding Items}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding ItemName}"> 
                        <TextBlock.ToolTip>
                            <ToolTip>
                                <Grid>
                                    <Grid.RowDefinitions>
                                        <RowDefinition />
                                        <RowDefinition />
                                    </Grid.RowDefinitions>
                                    <TextBlock Text="{Binding ItemDescription}" />
                                    <TextBlock Grid.Row="1" 
                   Text="{Binding Source={x:Static ToolTipSpike:Item.GlobalText},
                   Path=.}"
                                    />
                                </Grid>
                            </ToolTip>
                        </TextBlock.ToolTip>
                    </TextBlock>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </Grid>
</Window>

using System.Collections.Generic;
using System.Windows;

namespace ToolTipSpike
{
    public partial class Window1 : Window
    {

        public List<Item> Items { get; private set; }
        public Window1()
        {
            InitializeComponent();
            var itemList = new List<Item>
                  {
                      new Item { ItemName = "First Item", ItemDescription = "This is the first item." },
                      new Item { ItemName = "Second Item", ItemDescription = "This is the second item." }
                  };
            this.Items = itemList;
            this.DataContext = this;
       }
    }

     public class Item
     {
         static Item()
         {
             GlobalText = "Additional Text";
         }
         public static string GlobalText { get; set; }
         public string ItemName{ get; set;}
         public string ItemDescription{ get; set;}
     }
}

Problem

I am trying to display a tooltip for an item generated by an `ItemsControl` that needs to pull data from conceptually unrelated sources. For example, say I have an Item class as follows: ``` public class Item { public string ItemDescription { get; set; } public string ItemName { get; set; } } ``` I can display the Item within an ItemsControl with a tooltip as follows: ``` <ItemsControl x:Name="itemsControl" ItemsSource="{Binding Items}"> <ItemsControl.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding ItemName}"> <TextBlock.ToolTip> <ToolTip> <TextBlock Text="{Binding ItemDescription}" /> </ToolTip> </TextBlock.ToolTip> </TextBlock> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> ``` But say I have another property that can be accessed via the `DataContext` of the `ItemsControl`. Is there any way to do this from within the tooltip? E.g., ``` <ItemsControl x:Name="itemsControl" ItemsSource="{Binding Items}"> <ItemsControl.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding ItemName}"> <TextBlock.ToolTip> <ToolTip> <Grid> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition /> </Grid.RowDefinitions> <TextBlock Text="{Binding ItemDescription}" /> <TextBlock Grid.Row="1" Text="{Bind this to another property of the ItemsControl DataContext}" /> </Grid> </ToolTip> </TextBlock.ToolTip> </TextBlock> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> ``` The code for the test Window I used is as follows: ``` public partial class Window1 : Window { public Window1() { InitializeComponent(); List<Item> itemList = new List<Item>() { new Item() { ItemName = "First Item", ItemDescription = "This is the first item." }, new Item() { ItemName = "Second Item", ItemDescription = "This is the second item." } }; this.Items = itemList; this.GlobalText = "Something else for the tooltip."; this.DataContext = this; } public string GlobalText { get; private set; } public List<Item> Items { get; private set; } } ``` So in this example I want to show the value of the `GlobalText` property (in reality this would be another custom object). To complicate matters, I am actually using DataTemplates and show two different types of objects within the ItemsControl, but any assistance would be greatly appreciated!

Original source