C# 故事板找不到 ControlTemplate 元素

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/151752/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 15:46:43  来源:igfitidea点击:

Storyboards can't find ControlTemplate elements

提问by Kris Erickson

I've created some fairly simple XAML, and it works perfectly (at least in KAXML). The storyboards run perfectly when called from within the XAML, but when I try to access them from outside I get the error:

我已经创建了一些相当简单的 XAML,它工作得很好(至少在 KAXML 中)。当从 XAML 内部调用时,情节提要完美运行,但是当我尝试从外部访问它们时,出现错误:

'buttonGlow' name cannot be found in the name scope of 'System.Windows.Controls.Button'.

I am loading the XAML with a stream reader, like this:

我正在使用流阅读器加载 XAML,如下所示:

Button x = (Button)XamlReader.Load(stream);

And trying to run the Storyboard with:

并尝试使用以下命令运行 Storyboard:

Storyboard pressedButtonStoryboard =   
    Storyboard)_xamlButton.Template.Resources["ButtonPressed"];
pressedButtonStoryboard.Begin(_xamlButton);

I think that the problem is that fields I am animating are in the template and that storyboard is accessing the button.

我认为问题在于我正在制作动画的字段在模板中,而情节提要正在访问按钮。

Here is the XAML:

这是 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>

Any suggestions from anyone who understands WPF and XAML a lot better than me?

任何比我更了解 WPF 和 XAML 的人有什么建议吗?

Here is the error 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()

采纳答案by Kris Erickson

Finally found it. When you call Begin on storyboards that reference elements in the ControlTemplate, you must pass in the control template as well.

终于找到了。当您对引用 ControlTemplate 中元素的情节提要调用 Begin 时,您还必须传入控件模板。

Changing:

改变:

pressedButtonStoryboard.Begin(_xamlButton);

To:

到:

pressedButtonStoryboard.Begin(_xamlButton, _xamlButton.Template);

Fixed everything.

固定一切。

回答by cplotts

I think just had this problem.

我想刚刚有这个问题。

Let me refer you to my blog entry on the matter: http://www.cplotts.com/2008/09/26/dr-wpf-namescopes/

让我向您推荐我关于此事的博客条目:http: //www.cplotts.com/2008/09/26/dr-wpf-namescopes/

Basically, the trick is that you need to call Begin with an argument that is an object in the same name scope that the storyboards are targeting.

基本上,诀窍是您需要使用一个参数调用 Begin,该参数是故事板所针对的名称范围内的对象。

In particular, from your sample above, I would try to call Begin and send in a reference to the _background element in your template.

特别是,从上面的示例中,我会尝试调用 Begin 并发送对模板中 _background 元素的引用。

Let me know if this doesn't solve your problem.

如果这不能解决您的问题,请告诉我。

Update:

更新:

I like Erickson's solution better than mine ... and it worked for me too. I don't know how I missed that overload of the Begin method!

我比我更喜欢 Erickson 的解决方案……它也对我有用。我不知道我怎么错过了 Begin 方法的重载!

回答by Joel B Fant

I made it work by restructuring the XAML so that the SolidColorBrushand OuterGlowBitmapEffectwere resources of the button and thus referenced are shared by the Storyboards and the elements they're applied to. I retrieved the Storyboardand called Begin()on it just as you did, but here is the modified XAML for the Button:

我通过重组 XAML 使其工作,以便SolidColorBrushOuterGlowBitmapEffect是按钮的资源,因此被引用的Storyboards 和它们所应用的元素共享。我像你一样检索Storyboard并调用Begin()了它,但这里是修改后的 XAML Button

(Please note the keys "buttonGlow"and "borderBackground"and all StaticResourcemarkup extensions referencing them.)

(请注意键"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>

回答by Emmanuel

(@ Sam Meldrum) To get STOP working, add 'true for "isControllable" at the begin

(@ Sam Meldrum)要停止工作,请在开头为“isControllable”添加“true”

pressedButtonStoryboard.Begin(_xamlButton, _xamlButton.Template);

change to

改成

pressedButtonStoryboard.Begin(_xamlButton, _xamlButton.Template,true);

and now

现在

pressedButtonStoryboard.Stop(xamlButton)

will work

将工作

回答by ouflak

I ran into this error as well. My situation is a bit different, perhaps simpler. I have a WPF window that has a template with an animation on it. I then had a separate completely unrelated animation triggered by MouseEnter defined for a button, both on the window itself. I started getting 'button1 cannot be found in the namescope'. After playing around a bit with some of the ideas here and debugging the actual Namescope (put a watch on the result of NameScope.GetNameScope(this), I finally found the solution was to put:

我也遇到了这个错误。我的情况有点不同,也许更简单。我有一个 WPF 窗口,它有一个带有动画的模板。然后我有一个单独的完全不相关的动画,由为按钮定义的 MouseEnter 触发,两者都在窗口本身上。我开始收到“在名称范围中找不到 button1”的消息。在玩了一些这里的想法并调试实际的 Namescope 之后(观察 NameScope.GetNameScope(this) 的结果,我终于找到了解决方案:

 this.RegisterName("button1", this.button1);

in a MouseEnter method defined in code and attached to the button. This MouseEnter will be called before the xaml Trigger. Curiously, the register method does not work if it is in the constructor or Window.Activated() method. Hope this helps someone.

在代码中定义并附加到按钮的 MouseEnter 方法中。此 MouseEnter 将在 xaml 触发器之前调用。奇怪的是,如果 register 方法在构造函数或 Window.Activated() 方法中,则它不起作用。希望这可以帮助某人。