Раскадровки не могут найти элементы ControlTemplate
Я создал довольно простой XAML, и он отлично работает (по крайней мере, в KAXML). Раскадровки отлично работают при вызове из XAML, но когда я пытаюсь получить к ним доступ извне, я получаю сообщение об ошибке:
'buttonGlow' name cannot be found in the name scope of 'System.Windows.Controls.Button'.
Я загружаю XAML с помощью устройства чтения потоков, например:
Button x = (Button)XamlReader.Load(stream);
И попытка запустить раскадровку с помощью:
Storyboard pressedButtonStoryboard =
Storyboard)_xamlButton.Template.Resources["ButtonPressed"];
pressedButtonStoryboard.Begin(_xamlButton);
Я думаю, что проблема в том, что поля, которые я анимация, находятся в шаблоне, и эта раскадровка обращается к кнопке.
Вот XAML:
<Button xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:customControls="clr-namespace:pk_rodoment.SkinningEngine;assembly=pk_rodoment"
Width="150" Height="55">
<Button.Resources>
<Style TargetType="Button">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid Background="#00FFFFFF">
<Grid.BitmapEffect>
<BitmapEffectGroup>
<OuterGlowBitmapEffect x:Name="buttonGlow" GlowColor="#A0FEDF00" GlowSize="0"/>
</BitmapEffectGroup>
</Grid.BitmapEffect>
<Border x:Name="background" Margin="1,1,1,1" CornerRadius="15">
<Border.Background>
<SolidColorBrush Color="#FF0062B6"/>
</Border.Background>
</Border>
<ContentPresenter HorizontalAlignment="Center"
Margin="{TemplateBinding Control.Padding}"
VerticalAlignment="Center"
Content="{TemplateBinding ContentControl.Content}"
ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}"/>
</Grid>
<ControlTemplate.Resources>
<Storyboard x:Key="ButtonPressed">
<Storyboard.Children>
<DoubleAnimation Duration="0:0:0.4"
FillBehavior="HoldEnd"
Storyboard.TargetName="buttonGlow"
Storyboard.TargetProperty="GlowSize" To="4"/>
<ColorAnimation Duration="0:0:0.6"
FillBehavior="HoldEnd"
Storyboard.TargetName="background"
Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)"
To="#FF844800"/>
</Storyboard.Children>
</Storyboard>
<Storyboard x:Key="ButtonReleased">
<Storyboard.Children>
<DoubleAnimation Duration="0:0:0.2"
FillBehavior="HoldEnd"
Storyboard.TargetName="buttonGlow"
Storyboard.TargetProperty="GlowSize" To="0"/>
<ColorAnimation Duration="0:0:0.2"
FillBehavior="Stop"
Storyboard.TargetName="background"
Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)"
To="#FF0062B6"/>
</Storyboard.Children>
</Storyboard>
</ControlTemplate.Resources>
<ControlTemplate.Triggers>
<Trigger Property="ButtonBase.IsPressed" Value="True">
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource ButtonPressed}"/>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource ButtonReleased}"/>
</Trigger.ExitActions>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Button.Resources>
<DockPanel>
<TextBlock x:Name="TextContent" FontSize="28" Foreground="White" >Test</TextBlock>
</DockPanel>
</Button>
Любые предложения от любого, кто понимает WPF и XAML намного лучше меня?
Вот ошибка stacktrace:
at System.Windows.Media.Animation.Storyboard.ResolveTargetName(String targetName, INameScope nameScope, DependencyObject element)
at System.Windows.Media.Animation.Storyboard.ClockTreeWalkRecursive(Clock currentClock, DependencyObject containingObject, INameScope nameScope, DependencyObject parentObject, String parentObjectName, PropertyPath parentPropertyPath, HandoffBehavior handoffBehavior, HybridDictionary clockMappings, Int64 layer)
at System.Windows.Media.Animation.Storyboard.ClockTreeWalkRecursive(Clock currentClock, DependencyObject containingObject, INameScope nameScope, DependencyObject parentObject, String parentObjectName, PropertyPath parentPropertyPath, HandoffBehavior handoffBehavior, HybridDictionary clockMappings, Int64 layer)
at System.Windows.Media.Animation.Storyboard.BeginCommon(DependencyObject containingObject, INameScope nameScope, HandoffBehavior handoffBehavior, Boolean isControllable, Int64 layer)
at System.Windows.Media.Animation.Storyboard.Begin(FrameworkElement containingObject)
at pk_rodoment.SkinningEngine.ButtonControlWPF._button_MouseDown(Object sender, MouseButtonEventArgs e)
at System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
at System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted)
at System.Windows.Input.InputManager.ProcessStagingArea()
at System.Windows.Input.InputManager.ProcessInput(InputEventArgs input)
at System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport)
at System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawMouseActions actions, Int32 x, Int32 y, Int32 wheel)
at System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at System.Windows.Interop.HwndSource.InputFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Boolean isSingleParameter)
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler)
at System.Windows.Threading.Dispatcher.WrappedInvoke(Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler)
at System.Windows.Threading.Dispatcher.InvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Boolean isSingleParameter)
at System.Windows.Threading.Dispatcher.Invoke(DispatcherPriority priority, Delegate method, Object arg)
at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
at System.Windows.Threading.Dispatcher.Run()
at System.Windows.Application.RunDispatcher(Object ignore)
at System.Windows.Application.RunInternal(Window window)
at System.Windows.Application.Run(Window window)
at System.Windows.Application.Run()
at ControlTestbed.App.Main() in C:\svnprojects\rodomont\ControlsTestbed\obj\Debug\App.g.cs:line 0
at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
Ответы
Ответ 1
Наконец нашел его. Когда вы вызываете "Начать" на раскадровках, которые ссылаются на элементы в ControlTemplate, вы также должны пройти в шаблоне управления.
Изменение:
pressedButtonStoryboard.Begin(_xamlButton);
To:
pressedButtonStoryboard.Begin(_xamlButton, _xamlButton.Template);
Исправлено все.
Ответ 2
Я сделал это, реструктурируя XAML, чтобы SolidColorBrush
и OuterGlowBitmapEffect
были ресурсами кнопки и, таким образом, были разделены с помощью Storyboard
и элементов, к которым они применяются. Я получил Storyboard
и назвал Begin()
на нем так же, как вы, но вот измененный XAML для Button
:
(Обратите внимание на клавиши "buttonGlow"
и "borderBackground"
и все расширительные расширения StaticResource
, ссылающиеся на них.)
<Button
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="150"
Height="55">
<Button.Resources>
<OuterGlowBitmapEffect
x:Key="buttonGlow"
GlowColor="#A0FEDF00"
GlowSize="0" />
<SolidColorBrush
x:Key="borderBackground"
Color="#FF0062B6" />
<Style
TargetType="Button">
<Setter
Property="Control.Template">
<Setter.Value>
<ControlTemplate
TargetType="Button">
<Grid
Name="outerGrid"
Background="#00FFFFFF"
BitmapEffect="{StaticResource buttonGlow}">
<Border
x:Name="background"
Margin="1,1,1,1"
CornerRadius="15"
Background="{StaticResource borderBackground}">
</Border>
<ContentPresenter
HorizontalAlignment="Center"
Margin="{TemplateBinding Control.Padding}"
VerticalAlignment="Center"
Content="{TemplateBinding ContentControl.Content}"
ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}" />
</Grid>
<ControlTemplate.Resources>
<Storyboard
x:Key="ButtonPressed">
<Storyboard.Children>
<DoubleAnimation
Duration="0:0:0.4"
FillBehavior="HoldEnd"
Storyboard.Target="{StaticResource buttonGlow}"
Storyboard.TargetProperty="GlowSize"
To="4" />
<ColorAnimation
Duration="0:0:0.6"
FillBehavior="HoldEnd"
Storyboard.Target="{StaticResource borderBackground}"
Storyboard.TargetProperty="Color"
To="#FF844800" />
</Storyboard.Children>
</Storyboard>
<Storyboard
x:Key="ButtonReleased">
<Storyboard.Children>
<DoubleAnimation
Duration="0:0:0.2"
FillBehavior="HoldEnd"
Storyboard.Target="{StaticResource buttonGlow}"
Storyboard.TargetProperty="GlowSize"
To="0" />
<ColorAnimation
Duration="0:0:0.2"
FillBehavior="Stop"
Storyboard.Target="{StaticResource borderBackground}"
Storyboard.TargetProperty="Color"
To="#FF0062B6" />
</Storyboard.Children>
</Storyboard>
</ControlTemplate.Resources>
<ControlTemplate.Triggers>
<Trigger
Property="ButtonBase.IsPressed"
Value="True">
<Trigger.EnterActions>
<BeginStoryboard
Storyboard="{StaticResource ButtonPressed}" />
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard
Storyboard="{StaticResource ButtonReleased}" />
</Trigger.ExitActions>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Button.Resources>
<DockPanel>
<TextBlock
x:Name="TextContent"
FontSize="28"
Foreground="White">Test</TextBlock>
</DockPanel>
</Button>
Ответ 3
Я думаю, что была эта проблема.
Позвольте мне направить вас к моей записи в блоге по этому вопросу: http://www.cplotts.com/2008/09/26/dr-wpf-namescopes/
В принципе, трюк заключается в том, что вам нужно вызвать Begin с аргументом, который является объектом с тем же именем, на который нацелены раскадровки.
В частности, из приведенного выше примера я попытался вызвать Begin и отправить ссылку на элемент _background в вашем шаблоне.
Сообщите мне, если это не решит вашу проблему.
Update:
Мне нравится решение Эриксона лучше, чем мое... и это сработало и для меня. Я не знаю, как я пропустил эту перегрузку метода Begin!
Ответ 4
(@Sam Meldrum) Чтобы заставить STOP работать, добавьте true для "isControllable" в начале
pressedButtonStoryboard.Begin(_xamlButton, _xamlButton.Template);
измените на
pressedButtonStoryboard.Begin(_xamlButton, _xamlButton.Template,true);
и теперь
pressedButtonStoryboard.Stop(xamlButton)
будет работать
Ответ 5
Я столкнулся с этой ошибкой. Моя ситуация немного другая, возможно, проще. У меня есть окно WPF, в котором есть шаблон с анимацией. Затем у меня была отдельная полностью несвязанная анимация, инициированная MouseEnter для кнопки, как на самом окне. Я начал получать "button1 не может быть найден в обозревателе". Немного поработав с некоторыми идеями и отлаживая фактический Namescope (поставьте часы на результат NameScope.GetNameScope(это), я наконец нашел решение: поставить
this.RegisterName("button1", this.button1);
в методе MouseEnter, определенном в коде и прикрепленном к кнопке. Этот MouseEnter будет вызываться перед триггером xaml. Любопытно, что метод register не работает, если он находится в методе constructor или Window.Activated(). Надеюсь, это поможет кому-то.