XAML Binding to the Title of a Window does not always work {Relative Source, AncestorType=Window}.

Stout 286 Reputation points
2020-11-18T04:10:42.657+00:00

Hi. I need to databind two TextBlocks to the Window Title property. The first one works via "RelativeSource FindAncestor, AncestorType=Window}", but the second one does not (it's deeply nested within a button tooltip).

How can I change the second one to make it also display the Title of the Window?

Thanks.

<Window ...>
<Border ...>
<Grid ...>
<Grid ...>
<!-- TEXTBLOCK BELOW WORKS -->
<TextBlock Grid.Column="2" Text="{Binding Title, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}"
HorizontalAlignment="Stretch" VerticalAlignment="Center" Foreground="White" FontSize="18px" FontStretch="UltraExpanded" />
<Button Grid.Column="3" HorizontalAlignment="Right" VerticalAlignment="Stretch"
Background="Transparent" BorderBrush="Transparent" Foreground="Transparent"
ToolTipService.InitialShowDelay="0" ToolTipService.BetweenShowDelay="0" ToolTipService.ShowDuration="60000">
<Button.ToolTip>
<ToolTip x:Name="helpButtonTooltip" Width="240" ToolTipService.InitialShowDelay="0">
<!-- TEXTBLOCK BELOW DOES NOT WORK; HOW CAN I MAKE IT WORK? -->
<TextBlock Text="{Binding Title, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}"
HorizontalAlignment="Stretch" VerticalAlignment="Center" Foreground="White" FontSize="18px" FontStretch="UltraExpanded" />

Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,761 questions
0 comments No comments
{count} votes

Accepted answer
  1. Peter Fleischer (former MVP) 19,321 Reputation points
    2020-11-18T11:29:15.557+00:00

    Hi,
    you can use for instance of window an additional parameter (in ctor) to set string resource like in following demo:

    XAML MainWindow:

    <Window x:Class="WpfApp1.Window013"  
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"  
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"  
            xmlns:local="clr-namespace:WpfApp013"  
            mc:Ignorable="d"  
            Title="MainWindow" Height="450" Width="400">  
      <Window.DataContext>  
        <local:ViewModel/>  
      </Window.DataContext>  
      <StackPanel>  
        <Button Content="Window 1" Command="{Binding}" CommandParameter="1" Width="200" Margin="5"/>  
        <Button Content="Window 2" Command="{Binding}" CommandParameter="2" Width="200" Margin="5"/>  
      </StackPanel>  
    </Window>  
    

    ViewModel:

    using System;  
    using System.Windows;  
    using System.Windows.Input;  
      
    namespace WpfApp013  
    {  
      public class ViewModel : ICommand  
      {  
      
        public void Execute(object parameter)  
        {  
          WpfApp1.Window013A wnd;  
          switch (parameter.ToString())  
          {  
            case "1":  
              wnd = new WpfApp1.Window013A("Title 1");  
              wnd.Show();  
              break;  
            case "2":  
              wnd = new WpfApp1.Window013A("Title 2");  
              wnd.Show();  
              break;  
            default:  
              break;  
          }  
        }  
      
        public event EventHandler CanExecuteChanged;  
        public bool CanExecute(object parameter) => true;  
      }  
    }  
    

    Second Window with Title set in MainWindow:

    <Window x:Class="WpfApp1.Window013A"  
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"  
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"  
            xmlns:local="clr-namespace:WpfApp1"  
            xmlns:clr="clr-namespace:System;assembly=mscorlib"  
            mc:Ignorable="d"  
            Title="{StaticResource Title}" Height="450" Width="800">  
      <StackPanel>  
        <Button Content="Button"  
                Width="100"   
                Margin="5" HorizontalAlignment="Left"  
                ToolTipService.InitialShowDelay="0"   
                ToolTipService.BetweenShowDelay="0"   
                ToolTipService.ShowDuration="60000">  
          <Button.ToolTip>  
            <ToolTip x:Name="helpButtonTooltip"  
                     Width="240"   
                     ToolTipService.InitialShowDelay="0">  
              <TextBlock Text="{StaticResource Title}"  
                         HorizontalAlignment="Stretch"   
                         VerticalAlignment="Center"  
                         Foreground="Red"   
                         FontSize="18px"   
                         FontStretch="UltraExpanded" />  
            </ToolTip>  
          </Button.ToolTip>  
        </Button>  
      </StackPanel>  
    </Window>  
    

    And CodeBehind:

    using System.Windows;  
      
    namespace WpfApp1  
    {  
      public partial class Window013A : Window  
      {  
        public Window013A(string title)  
        {  
          this.Resources.Add("Title", title);  
          InitializeComponent();  
        }  
      }  
    }  
    

    Result:

    40744-x.gif

    1 person found this answer helpful.
    0 comments No comments

2 additional answers

Sort by: Most helpful
  1. Peter Fleischer (former MVP) 19,321 Reputation points
    2020-11-18T06:06:41.783+00:00

    HI,
    your ToolTip is outside Window, see VisualTree:

    40614-x.png

    You can use MVVM with Binding like this:

    <Window x:Class="Window068"  
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"  
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"  
            xmlns:local="clr-namespace:WpfApp1.WpfApp068"  
            mc:Ignorable="d"  
            Title="{Binding Title}" Height="200" Width="300">  
      <Border BorderBrush="Gold"   
              BorderThickness="3">  
        <Grid Background="gray">  
          <Grid>  
            <Grid.ColumnDefinitions>  
              <ColumnDefinition/>  
              <ColumnDefinition/>  
              <ColumnDefinition/>  
            </Grid.ColumnDefinitions>  
            <!-- TEXTBLOCK BELOW WORKS -->  
            <TextBlock Grid.Column="2"   
                       Text="{Binding Title}"  
                       HorizontalAlignment="Stretch"   
                       VerticalAlignment="Center"   
                       Foreground="White"   
                       FontSize="18px"   
                       FontStretch="UltraExpanded"/>  
            <Button Grid.Column="3"   
                    HorizontalAlignment="Right"   
                    VerticalAlignment="Stretch"  
                    Background="Transparent"   
                    BorderBrush="Transparent"   
                    Foreground="Transparent"   
                    ToolTipService.InitialShowDelay="0"   
                    ToolTipService.BetweenShowDelay="0"   
                    ToolTipService.ShowDuration="60000">  
              <Button.ToolTip>  
                <ToolTip x:Name="helpButtonTooltip"  
                         Width="240"   
                         ToolTipService.InitialShowDelay="0">  
                   <!--TEXTBLOCK BELOW DOES NOT WORK; HOW CAN I MAKE IT WORK?-->   
                  <TextBlock Text="{Binding Title}"  
                             HorizontalAlignment="Stretch"   
                             VerticalAlignment="Center"  
                             Foreground="Red"   
                             FontSize="18px"   
                             FontStretch="UltraExpanded" />  
                </ToolTip>  
              </Button.ToolTip>  
            </Button>  
          </Grid>  
          </Grid>  
        </Border>  
    </Window>  
    

    And CodeBehind and ViewModel:

    Public Class Window068  
      Public Sub New()  
        Dim vm As New WpfApp068.ViewModel  
        Me.Resources.Add("vm", vm)  
        Me.DataContext = vm  
        ' This call is required by the designer.  
        InitializeComponent()  
      
        ' Add any initialization after the InitializeComponent() call.  
      
      End Sub  
    End Class  
      
      
    Namespace WpfApp068  
      Public Class ViewModel  
        Public Property Title As String = "new Title"  
      End Class  
    End Namespace  
    

    Result:

    40505-x.png

    1 person found this answer helpful.

  2. Stout 286 Reputation points
    2020-11-18T07:17:33.127+00:00

    Hi Peter. Thank you for explaining the Live Visual Tree. It helps me understand the whole picture.

    My problem is that I cannot use the data straight from the ViewModel. The reason is that I have a single ViewModel, and many Views (Windows) setting their DataContext to that ViewModel.

    So in my ViewModel I'm doing this kind of code:

                MyWindows.AddWindow(Content: new MyUserControl_1(this), // Different Views for the same ViewModel
                                        Owner: Owner,
                                        Title: "Title 1", // Different Title for each Window (to be displayed as a Tooltip)
                                        Width: 400,
                                        Height: 200,
                                        DataContext: this); // Same DataContext for the two Views
    
                MyWindows.AddWindow(Content: new MyUserControl_2(this), // Different Views for the same ViewModel
                                        Owner: Owner,
                                        Title: "Title 2", // Different Title for each Window (to be displayed as a Tooltip)
                                        Width: 400,
                                        Height: 200,
                                        DataContext: this); // Same DataContext for the two Views
    

    Is there any hope with the current design?

    Thank you.

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.