简体   繁体   中英

Name scope issues due to binding to event that gets fired before template layout

Based on some standard web searching, I have narrowed down my problem to this: I believe the event that fires my storyboard gets invoked prior to the template being expanded. Thus, names are meaningless, and name references made by the storyboard's animations are null.

This would not be an issue if I were not working with a ControlTemplate. I could just bind to the event after the layout is updated, then manually invoke it the first time around. Problem solved. However, since this is a ControlTemplate in its own resource dictionary XAML file, I can't use C# to solve this problem.

(Update: I can definitively say that this is not an ordering issue--in other words, it has nothing to do with having defined the contents before ControlTemplate.Resources or similar. However, similar problems can be caused by such ordering issues, so this matter is worth investigating if you are encountering similar problems. See one of the answers below made before this update for a more detailed explanation.)

Then again, I could be on the wrong track entirely. This is just my understanding of what is going on behind the curtain. So that you can judge for yourself, here is the actual exception:

System.InvalidOperationException:
{"'PART_UnderlineBrush' name cannot be found in the name scope of 'System.Windows.Controls.ControlTemplate'."}

Here is the style/template for reference, with all the extra stuff (storyboards, properties, etc.) removed.

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Style x:Key="MetroTabItem" TargetType="{x:Type TabItem}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type TabItem}">
                    <Border>
                        <Border.BorderBrush>
                            <!-- This is the element that I need to reference, but I am unable to do so. -->
                            <SolidColorBrush Color="#00ffffff" x:Name="PART_UnderlineBrush" />
                        </Border.BorderBrush>
                        <ContentPresenter Content="{TemplateBinding Header}"
                                          ContentTemplate="{TemplateBinding HeaderTemplate}" />
                    </Border>
                    <ControlTemplate.Resources>
                        <Storyboard x:Key="SelectTab">
                            <!-- This is the animation that will always fail, due to the name reference. -->
                            <ColorAnimation BeginTime="0:0:0"
                                            Duration="0:0:0.5"
                                            Storyboard.TargetProperty="Color"
                                            Storyboard.TargetName="PART_UnderlineBrush"
                                            To="#ddffffff" />
                        </Storyboard>
                    </ControlTemplate.Resources>
                    <ControlTemplate.Triggers>
                        <EventTrigger RoutedEvent="Selector.Selected">
                            <BeginStoryboard Name="BeginSelected" Storyboard="{StaticResource SelectTab}" />
                        </EventTrigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

I don't know if this will do exactly what you want, but if you replace your EventTrigger with a Trigger for the IsSelected property of the TabItem it might work:

<ControlTemplate.Triggers>
    <Trigger Property="IsSelected" Value="True">
        <Trigger.EnterActions>
            <BeginStoryboard Name="BeginSelected" Storyboard="{StaticResource SelectTab}" />
        </Trigger.EnterActions>
    </Trigger>
</ControlTemplate.Triggers>

There does seem to be some timing issue going on with the original code. The Selector.Selected event seems to be fired before the control has loaded.

Put your

<ControlTemplate.Resources>

before the

<Border>

Full code:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="MetroTabItem" TargetType="{x:Type TabItem}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type TabItem}">
                <ControlTemplate.Resources>
                    <Storyboard x:Key="SelectTab">
                        <!-- This is the animation that will always fail, due to the name reference. -->
                        <ColorAnimation BeginTime="0:0:0"
                                        Duration="0:0:0.5"
                                        Storyboard.TargetProperty="Color"
                                        Storyboard.TargetName="PART_UnderlineBrush"
                                        To="#ddffffff" />
                    </Storyboard>
                </ControlTemplate.Resources>
                <ControlTemplate.Triggers>
                    <EventTrigger RoutedEvent="Selector.Selected">
                        <BeginStoryboard Name="BeginSelected" Storyboard="{StaticResource SelectTab}" />
                    </EventTrigger>
                </ControlTemplate.Triggers>
                <Border>
                    <Border.BorderBrush>
                        <!-- This is the element that I need to reference, but I am unable to do so. -->
                        <SolidColorBrush Color="#00ffffff" x:Name="PART_UnderlineBrush" />
                    </Border.BorderBrush>
                    <ContentPresenter Content="{TemplateBinding Header}"
                                      ContentTemplate="{TemplateBinding HeaderTemplate}" />
                </Border>               
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM