Monday, June 3, 2019

Complex bindings in XAML

I have a requirement to display a dynamic tool tip on a tab item's header. My problem is that the property isn't in the tab control's data context or even in the tab item's data context. It's in a different tab item's data context. How to bind to it in XAML?

Fortunately the property is in the first tab's data context. That's a life saver.

Start a new WPF project called ExtendedBinding in C#. Replace the contents of MainWindow.xaml with this. It defines a Search tab with a content and an Add tab with a tooltip. The tooltip is bound to a property in the content of the search tab.


<Window x:Class="ExtendedBinding.MainWindow"
        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:ExtendedBinding"
        mc:Ignorable="d"
        DataContext="{Binding RelativeSource={RelativeSource Self}}"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <local:cClass x:Key="content"/>
    </Window.Resources>
    <Grid>
        <TabControl>
            <TabItem Header="Search" Content="{StaticResource content}"/>
            <TabItem Header="Add" ToolTip="{Binding Path=Items[0].Content.text, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=TabControl}}"/>
        </TabControl>
    </Grid>
</Window>

The fun part is here. It says "go find the next ancestor that is a tab control, get the first item's content, and display the text property. Note I don't need to tell the XAML that the content is an ExtendedBinding.cClass.

ToolTip="{Binding Path=Items[0].Content.text, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=TabControl}}"

You can leave the MainWindow.xaml.cs alone but you do need to add a class to act as the content for the Search tab. Add a class called cClass like this. Obviously you will initialize the text property differently in reality.


namespace ExtendedBinding
{
    public class cClass
    {
        private string _text = "Add is enabled";
        public string text
        {
            get { return _text; }
            set { _text = value; }
        }
    }
}

The result is this. The Add tab's tooltip is pulled from the Search tab's context.


No comments:

Post a Comment