绑定ToggleButton的IsChecked属性后触发InvalidOperationException:未找到Ellipse
问题
使用ToggleButton自定义样式后,将IsChecked属性绑定到ViewModel的IsAutostop属性时,程序崩溃并抛出System.InvalidOperationException,错误提示在System.Windows.Controls.ControlTemplate中未找到名为Ellipse的元素。
自定义样式代码
<Style TargetType="{x:Type ToggleButton}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ToggleButton}"> <Viewbox> <Border x:Name="Border" CornerRadius="10" Background="#FFE2E2E2" Width="40" Height="20"> <Border.Effect> <DropShadowEffect ShadowDepth="0.5" Direction="0" Opacity="0.3" /> </Border.Effect> <Ellipse x:Name="Ellipse" Fill="#FF909090" Stretch="Uniform" Margin="-8 -4" Stroke="Gray" StrokeThickness="0.2" HorizontalAlignment="Stretch"> <Ellipse.Effect> <DropShadowEffect BlurRadius="10" ShadowDepth="1" Opacity="0.3" Direction="260" /> </Ellipse.Effect> </Ellipse> </Border> </Viewbox> <ControlTemplate.Triggers> <EventTrigger RoutedEvent="Checked"> <BeginStoryboard> <Storyboard> <ColorAnimation Storyboard.TargetName="Ellipse" Storyboard.TargetProperty="(Ellipse.Fill).(SolidColorBrush.Color)" To="#00facc" Duration="0:0:0.05" AccelerationRatio="0.7" DecelerationRatio="0.3" /> <ThicknessAnimation Storyboard.TargetName="Ellipse" Storyboard.TargetProperty="Margin" To="20 -4 -8 -4" Duration="0:0:0.15" AccelerationRatio="0.7" DecelerationRatio="0.3" /> </Storyboard> </BeginStoryboard> </EventTrigger> <EventTrigger RoutedEvent="Unchecked"> <BeginStoryboard> <Storyboard> <ColorAnimation Storyboard.TargetName="Ellipse" Storyboard.TargetProperty="(Ellipse.Fill).(SolidColorBrush.Color)" To="#00facc" Duration="0:0:0.05" AccelerationRatio="0.7" DecelerationRatio="0.3" /> <ThicknessAnimation Storyboard.TargetName="Ellipse" Storyboard.TargetProperty="Margin" To="-8 -4" Duration="0:0:0.15" AccelerationRatio="0.7" DecelerationRatio="0.3" /> </Storyboard> </BeginStoryboard> </EventTrigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style>
使用方式
<ToggleButton Grid.Column="0" Grid.Row="2" IsChecked="{Binding IsAutostop}"/>
补充场景
通过任务栏图标的命令触发窗口打开:
WindowService代码
class WindowService { public void OpenOptionsView(MainViewModel mvm) { OptionsView optionsView = new OptionsView { DataContext = mvm }; optionsView.Show(); } }
MainViewModel关键代码
public ICommand OpenOptionsViewCommand { get; private set; } public bool IsAutostop { get { return Settings.Default.Autostop; } set { Settings.Default.Autostop = value; Settings.Default.Save(); OnPropertyChanged(); } } public MainViewModel() { OpenOptionsViewCommand = new RelayCommand(OpenOptionsView, param => true); } private void OpenOptionsView(object o) { WindowService ws = new WindowService(); ws.OpenOptionsView(this); }
任务栏图标XAML
<tb:TaskbarIcon> <tb:TaskbarIcon.ContextMenu> <ContextMenu Background="#1e1e1e"> <MenuItem Header="Programm öffnen" Foreground="White" Command="{Binding OpenOptionsViewCommand}"/> </ContextMenu> </tb:TaskbarIcon.ContextMenu> </tb:TaskbarIcon>
解决方案
1. 替换EventTrigger为PropertyTrigger
问题根源在于Checked/Unchecked事件可能在ControlTemplate内的Ellipse元素尚未完成初始化时就触发,导致动画找不到目标元素。改用监听IsChecked属性变化的Trigger可以避免这个问题,因为属性触发会等待模板元素加载完成后再执行:
修改ControlTemplate的Triggers部分:
<ControlTemplate.Triggers> <Trigger Property="IsChecked" Value="True"> <Trigger.EnterActions> <BeginStoryboard> <Storyboard> <ColorAnimation Storyboard.TargetName="Ellipse" Storyboard.TargetProperty="(Ellipse.Fill).(SolidColorBrush.Color)" To="#00facc" Duration="0:0:0.05" AccelerationRatio="0.7" DecelerationRatio="0.3" /> <ThicknessAnimation Storyboard.TargetName="Ellipse" Storyboard.TargetProperty="Margin" To="20 -4 -8 -4" Duration="0:0:0.15" AccelerationRatio="0.7" DecelerationRatio="0.3" /> </Storyboard> </BeginStoryboard> </Trigger.EnterActions> <Trigger.ExitActions> <BeginStoryboard> <Storyboard> <!-- 取消选中时恢复为原始灰色 --> <ColorAnimation Storyboard.TargetName="Ellipse" Storyboard.TargetProperty="(Ellipse.Fill).(SolidColorBrush.Color)" To="#FF909090" Duration="0:0:0.05" AccelerationRatio="0.7" DecelerationRatio="0.3" /> <ThicknessAnimation Storyboard.TargetName="Ellipse" Storyboard.TargetProperty="Margin" To="-8 -4" Duration="0:0:0.15" AccelerationRatio="0.7" DecelerationRatio="0.3" /> </Storyboard> </BeginStoryboard> </Trigger.ExitActions> </Trigger> </ControlTemplate.Triggers>
2. 修复动画颜色错误
原代码中Unchecked事件的ColorAnimation目标颜色错误设置为#00facc,取消选中时应该恢复为初始的灰色#FF909090,上述代码已修正该问题。
3. 延迟DataContext设置(可选)
如果问题仍然存在,可以在窗口Loaded事件触发后再设置DataContext,确保模板完全加载:
修改WindowService的代码:
public void OpenOptionsView(MainViewModel mvm) { OptionsView optionsView = new OptionsView(); optionsView.Loaded += (s, e) => { optionsView.DataContext = mvm; }; optionsView.Show(); }
内容的提问来源于stack exchange,提问作者Schulze
相关产品推荐
相关产品推荐

