Why is this combination of TabControl - DataTrigger - Storyboard not working?

112 views Asked by At

I've encountered some kind of binding error in my program, which I can't explain by myself.

I wanted to style a TextBox, so that it displays a warning icon if the value is not covered by some product specification. When the user hovers the cursor over the icon, a more detailed warning message should appear in an AdornerLayer.

Screenshot of the application

As you can see, the control works, but I still have a question about it. To describe my problem, I have reduced the code to its absolute minimum:

My code

App.xaml

<Application x:Class="WpfApplication3.App"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:ThemesAero="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"
         StartupUri="MainWindow.xaml">
    <Application.Resources>
        <Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type TextBox}">
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition />
                                <ColumnDefinition Width="Auto" />
                            </Grid.ColumnDefinitions>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="22" />
                                <RowDefinition />
                            </Grid.RowDefinitions>
                            <ThemesAero:ListBoxChrome x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderFocused="{TemplateBinding IsKeyboardFocusWithin}" SnapsToDevicePixels="True">
                                <ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                            </ThemesAero:ListBoxChrome>
                            <Image Name="WarningIcon" Margin="5,0,0,0" Grid.Column="1" RenderOptions.BitmapScalingMode="HighQuality" Source="warning_256x256.png" />
                            <Border x:Name="InformationBorder" Background="#E1BA18" Margin="5,0,0,0" Grid.Row="1" Grid.ColumnSpan="2" Opacity="0" CornerRadius="1.5" IsHitTestVisible="False" MinHeight="24" MaxWidth="267" VerticalAlignment="Bottom" HorizontalAlignment="Left">
                                <TextBlock Text="This is some warning message." Foreground="White" Margin="8,3,8,3" TextWrapping="Wrap"/>
                            </Border>
                        </Grid>
                        <ControlTemplate.Triggers>
                            <DataTrigger Binding="{Binding ElementName=WarningIcon, Path=IsMouseOver}" Value="True">
                                <DataTrigger.EnterActions>
                                    <BeginStoryboard x:Name="fadeInStoryboard">
                                        <Storyboard>
                                            <DoubleAnimation Duration="00:00:00.15" Storyboard.TargetName="InformationBorder" Storyboard.TargetProperty="Opacity" To="1"/>
                                        </Storyboard>
                                    </BeginStoryboard>
                                </DataTrigger.EnterActions>
                                <DataTrigger.ExitActions>
                                    <StopStoryboard BeginStoryboardName="fadeInStoryboard"/>
                                    <BeginStoryboard x:Name="fadeOutStoryBoard">
                                        <Storyboard>
                                            <DoubleAnimation Duration="00:00:00.15" Storyboard.TargetName="InformationBorder" Storyboard.TargetProperty="Opacity" To="0"/>
                                        </Storyboard>
                                    </BeginStoryboard>
                                </DataTrigger.ExitActions>
                            </DataTrigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Application.Resources>
</Application>

MainWindow.xaml

<Window x:Class="WpfApplication3.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
    <Grid>
        <TabControl>
            <TabItem Header="Debug 1">
                <TextBox Height="80" Width="150" />
            </TabItem>
            <TabItem Header="Debug 2">
                <TextBox Height="80" Width="150" />
            </TabItem>
        </TabControl>
    </Grid>
</Window>

What is my problem exactly?

What do we have here? I've applied the Style to two TextBoxes in a TabControl.

On the first TabItem (Debug 1), the IsMouseOver trigger works just fine and fades the warning message in and out.

However, an identical TextBox on the second TabItem (Debug 2) throws the following error and the IsMouseOver trigger isn't working at all.

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'ElementName=WarningIcon'. BindingExpression:Path=IsMouseOver; DataItem=null; target element is 'TextBox' (Name=''); target property is 'NoTarget' (type 'Object')

What have I tried to solve the problem?

As I read some suggested solutions on how to fix this, I finally noticed that all of the following triggers are working fine:

<DataTrigger Binding="{Binding ElementName=WarningIcon, Path=IsMouseOver}" Value="True">
    <Setter TargetName="InformationBorder" Property="Opacity" Value="1" />
</DataTrigger>

--

<Trigger SourceName="WarningIcon" Property="IsMouseOver" Value="True">
    <Trigger.EnterActions>
        <BeginStoryboard x:Name="fadeInStoryboard">
            <Storyboard>
                <DoubleAnimation Duration="00:00:00.15" Storyboard.TargetName="InformationBorder" Storyboard.TargetProperty="Opacity" To="1"/>
            </Storyboard>
        </BeginStoryboard>
    </Trigger.EnterActions>
    <Trigger.ExitActions>
        <StopStoryboard BeginStoryboardName="fadeInStoryboard"/>
        <BeginStoryboard x:Name="fadeOutStoryBoard">
            <Storyboard>
                <DoubleAnimation Duration="00:00:00.15" Storyboard.TargetName="InformationBorder" Storyboard.TargetProperty="Opacity" To="0"/>
            </Storyboard>
        </BeginStoryboard>
    </Trigger.ExitActions>
</Trigger>

--

<Trigger SourceName="WarningIcon" Property="IsMouseOver" Value="True">
    <Setter TargetName="InformationBorder" Property="Opacity" Value="1" />
</Trigger>

This error only occurs when I use a DataTrigger with two Storyboards in a TabControl, but why? I already know how to fix this, so I'm just interested what's happening behind the scenes.

0

There are 0 answers