wpf icon indicating copy to clipboard operation
wpf copied to clipboard

ControlTemplate NameScope bug when ToggleButton is inside a 'non-first' TabItem

Open Outofnothing opened this issue 1 year ago • 0 comments

Description

I have a custom style of ToggleButton, when I

  • put the ToggleButton inside a non-first TabItem
  • bind its IsChecked value to ViewModel
  • sets the default value in the ViewModel to True

The app will crash with error message System.InvalidOperationException: Name cannot be found in the namescope of System.Windows.Controls.ControlTemplate

Reproduction Steps

MainWindow.xaml:

<Window.Resources>
    <Style x:Key="SwitchButton" TargetType="{x:Type ToggleButton}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ToggleButton}">
                    <Viewbox>
                        <Border
                        x:Name="_Border"
                        Width="40"
                        Height="20"
                        Background="#FFFFFFFF"
                        CornerRadius="10">
                            <Border.Effect>
                                <DropShadowEffect
                                Direction="0"
                                Opacity="0.3"
                                ShadowDepth="0.5" />
                            </Border.Effect>
                            <Ellipse
                            x:Name="_Ellipse"
                            Margin="2,1,2,1"
                            HorizontalAlignment="Stretch"
                            Fill="#FFFFFFFF"
                            Stretch="Uniform"
                            Stroke="Gray"
                            StrokeThickness="0.2">
                                <Ellipse.Effect>
                                    <DropShadowEffect
                                    BlurRadius="10"
                                    Direction="260"
                                    Opacity="0.3"
                                    ShadowDepth="1" />
                                </Ellipse.Effect>
                            </Ellipse>
                        </Border>
                    </Viewbox>
                    <ControlTemplate.Triggers>
                        <EventTrigger RoutedEvent="Checked">
                            <BeginStoryboard>
                                <Storyboard>
                                    <ColorAnimation
                                    Storyboard.TargetName="_Border"
                                    Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"
                                    To="#12a5fd"
                                    Duration="0:0:0.1" />
                                    <ThicknessAnimation
                                    Storyboard.TargetName="_Ellipse"
                                    Storyboard.TargetProperty="Margin"
                                    To="20 1 2 1"
                                    Duration="0:0:0.1" />
                                </Storyboard>
                            </BeginStoryboard>
                        </EventTrigger>
                        <EventTrigger RoutedEvent="Unchecked">
                            <BeginStoryboard>
                                <Storyboard>
                                    <ColorAnimation
                                    Storyboard.TargetName="_Border"
                                    Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"
                                    To="White"
                                    Duration="0:0:0.1" />
                                    <ThicknessAnimation
                                    Storyboard.TargetName="_Ellipse"
                                    Storyboard.TargetProperty="Margin"
                                    To="2 1 2 1"
                                    Duration="0:0:0.1" />
                                </Storyboard>
                            </BeginStoryboard>
                        </EventTrigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Window.Resources>
<TabControl>
    <TabItem>
        <Label>Test</Label>
    </TabItem>
    <TabItem>
        <ToggleButton IsChecked="{Binding IsBusy}" Style="{StaticResource SwitchButton}" />
    </TabItem>
</TabControl>

MainWindow.xaml.cs

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new ViewModel();
    }
}

public class ViewModel
{
    public bool IsBusy { get; set; } = true;
}

Expected behavior

IsSelected property of ToggleButton can bind to ViewModel.

Actual behavior

The app crashes with error message 'System.InvalidOperationException: Name cannot be found in the namescope of System.Windows.Controls.ControlTemplate'

Regression?

No response

Known Workarounds

Use Trigger instead of EventTrigger in the ControlTemplate

<ControlTemplate.Triggers>
    <Trigger Property="IsChecked" Value="True">
        <Trigger.EnterActions>
            <BeginStoryboard>
                <Storyboard>
                    <ColorAnimation
                        Storyboard.TargetName="_Border"
                        Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"
                        To="#12a5fd"
                        Duration="0:0:0.1" />
                    <ThicknessAnimation
                        Storyboard.TargetName="_Ellipse"
                        Storyboard.TargetProperty="Margin"
                        To="20 1 2 1"
                        Duration="0:0:0.1" />
                </Storyboard>
            </BeginStoryboard>
        </Trigger.EnterActions>
        <Trigger.ExitActions>
            <BeginStoryboard>
                <Storyboard>
                    <ColorAnimation
                        Storyboard.TargetName="_Border"
                        Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"
                        To="White"
                        Duration="0:0:0.1" />
                    <ThicknessAnimation
                        Storyboard.TargetName="_Ellipse"
                        Storyboard.TargetProperty="Margin"
                        To="2 1 2 1"
                        Duration="0:0:0.1" />
                </Storyboard>
            </BeginStoryboard>
        </Trigger.ExitActions>
    </Trigger>
</ControlTemplate.Triggers>

Impact

No response

Configuration

  • .NET 8.0
  • Windows 10
  • x64

Other information

No response

Outofnothing avatar Mar 21 '24 01:03 Outofnothing