使用触发器时出现奇怪的 NullReferenceException

发布于 2024-10-28 20:49:12 字数 3415 浏览 1 评论 0原文

我有一个非常简单的 TabItem 模板,以及一个 MultiTrigger,其中一个 SourceName 属性用于一个 Condition。以下 XAML 在启动时抛出 NullReferenceException ,没有任何有用的信息可以帮助我解决问题。

最奇怪的是,如果删除 SourceName 属性,代码会很好地工作。或者,如果您保留 SourceName 属性,但删除 MultiTrigger.EnterActions 并使用标准 Setter,那么它也可以工作。只有 SourceName 属性和 MultiTrigger.EnterActions 的组合会无缘无故地抛出 NullReferenceException。那么这有什么问题呢?

<Window x:Class="WpfApplication2.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" WindowStartupLocation="CenterScreen">

    <Window.Resources>
        <Style TargetType="TabItem">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="TabItem">
                        <ControlTemplate.Resources>
                            <Storyboard x:Key="Storyboard_TabItem_Hover">
                                <DoubleAnimationUsingKeyFrames Storyboard.TargetName="background" Storyboard.TargetProperty="Opacity">
                                    <SplineDoubleKeyFrame KeyTime="00:00:00.3" Value="0.1" />
                                </DoubleAnimationUsingKeyFrames>
                            </Storyboard>
                        </ControlTemplate.Resources>

                        <Border x:Name="background" BorderBrush="Red" BorderThickness="1" Background="Yellow">
                            <Label Grid.Column="1" Content="{TemplateBinding Header}" />
                        </Border>

                        <ControlTemplate.Triggers>
                            <MultiTrigger>
                                <MultiTrigger.Conditions>
                                    <Condition Property="IsMouseOver" Value="True" SourceName="background" />
                                    <Condition Property="IsSelected" Value="False" />
                                </MultiTrigger.Conditions>

                                <MultiTrigger.EnterActions>
                                    <BeginStoryboard x:Name="sbHover" Storyboard="{StaticResource Storyboard_TabItem_Hover}"/>
                                </MultiTrigger.EnterActions>
                            </MultiTrigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>

    <TabControl Margin="10">
        <TabItem Header="Tab 1" />
        <TabItem Header="Tab 2" />
        <TabItem Header="Tab 3" />
        <TabItem Header="Tab 4" />
    </TabControl>
</Window>

更新

Greg Sansom 指出,有一个使用 MultiDataTriggerBinding 的简单解决方法。但是,我仍然想知道为什么首先抛出异常。我疯狂地搜索了 Google 和 MSDN,但什么也没找到。那么问题出在哪里呢?

I have a very simple TabItem template, and a single MultiTrigger with a SourceName attribute used on one Condition. The following XAML throws NullReferenceException when started, with no helpful info which would help me to fix the problem.

The strangest thing about this is the code works great if you remove the SourceName attribute. Or, if you leave the SourceName attribute, but remove MultiTrigger.EnterActions and use standard Setters instead, then it works as well. Only the combination of SourceName attribute and MultiTrigger.EnterActions throws NullReferenceException for no obvious reason. So what's wrong with this?

<Window x:Class="WpfApplication2.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" WindowStartupLocation="CenterScreen">

    <Window.Resources>
        <Style TargetType="TabItem">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="TabItem">
                        <ControlTemplate.Resources>
                            <Storyboard x:Key="Storyboard_TabItem_Hover">
                                <DoubleAnimationUsingKeyFrames Storyboard.TargetName="background" Storyboard.TargetProperty="Opacity">
                                    <SplineDoubleKeyFrame KeyTime="00:00:00.3" Value="0.1" />
                                </DoubleAnimationUsingKeyFrames>
                            </Storyboard>
                        </ControlTemplate.Resources>

                        <Border x:Name="background" BorderBrush="Red" BorderThickness="1" Background="Yellow">
                            <Label Grid.Column="1" Content="{TemplateBinding Header}" />
                        </Border>

                        <ControlTemplate.Triggers>
                            <MultiTrigger>
                                <MultiTrigger.Conditions>
                                    <Condition Property="IsMouseOver" Value="True" SourceName="background" />
                                    <Condition Property="IsSelected" Value="False" />
                                </MultiTrigger.Conditions>

                                <MultiTrigger.EnterActions>
                                    <BeginStoryboard x:Name="sbHover" Storyboard="{StaticResource Storyboard_TabItem_Hover}"/>
                                </MultiTrigger.EnterActions>
                            </MultiTrigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>

    <TabControl Margin="10">
        <TabItem Header="Tab 1" />
        <TabItem Header="Tab 2" />
        <TabItem Header="Tab 3" />
        <TabItem Header="Tab 4" />
    </TabControl>
</Window>

Update

As Greg Sansom pointed out, there is a simple workaround using MultiDataTrigger and Binding. However, I would still like to know why is the exception being thrown in the first place. I've searched Google and MSDN like crazy but haven't found anything. So what's the problem?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

入怼 2024-11-04 20:49:12

您可以通过将 MultiTrigger 更改为 MultiDataTrigger,并指定 Binding 而不是 SourceName 来解决此问题:

   <MultiDataTrigger.Conditions>
        <Condition Binding="{Binding ElementName=bg,Path=IsMouseOver}" 
Value="True"  />
        <Condition Binding="{Binding RelativeSource={RelativeSource Self},
 Path=IsSelected}" Value="False" />
    </MultiDataTrigger.Conditions>

You can work around the problem by changing the MultiTrigger to a MultiDataTrigger, and specifying Binding instead of SourceName:

   <MultiDataTrigger.Conditions>
        <Condition Binding="{Binding ElementName=bg,Path=IsMouseOver}" 
Value="True"  />
        <Condition Binding="{Binding RelativeSource={RelativeSource Self},
 Path=IsSelected}" Value="False" />
    </MultiDataTrigger.Conditions>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文