WPF使用无法启动的情节提要动态创建的UserControl

问题描述

我在运行.net WPF中动态创建的UserControl的Storyboard时遇到问题。

这些是我的课程的示例:

class EventsPage {

    //  ...    

    public void AddEvent(Event @event) {
        var eventUC = new EventUserContrl(@event);
        eventUC.ExpandCollapseAnimation += ExpandCollapseAnimation;
        EventsStackPanel.Children.Add(eventUC);
    }

    private ExpandCollapseAnimation(EventUserControl eventUC,double height,double time) {

        //  Create frames using custom functions for creating them.
        var frames = new DoubleKeyFrameCollection() {
            StoryBoardsBuilder.CreateEasingDoubleKeyFrame(0.0,eventUC.ActualHeight),StoryBoardsBuilder.CreateEasingDoubleKeyFrame(time,destinationHeight)
        };

        //  Create Animation.
        var heightSizeAnimation= StoryBoardsBuilder.BuildDoubleAnimationUsingKeyFrames(
                FillBehavior.Stop,frames,eventUC.Name,new PropertyPath("Height"));

        //  Create StoryBoard.
        var storyboard = new Storyboard();

        //  Add Animations into StoryBoard.
        storyboard.Children.Add(heightSizeAnimation);

        //  Create final function.
        storyboard.Completed += (sender,e) => {
            eventUC.Height = destinationHeight;
        };

        //  Run animation.
        storyboard.Begin(this);
    }

    //  ...

}

启动后,在storyboard.Begin(this)处显示异常:
System.InvalidOperationException: „Name „” cannot be found in the namespace „ProjectName.Pages.EventsPage ”.”

我做了类似的事情,但是是为了在页面中手动放置用户控件,它可以工作,但是不能。

这是StoryBuilder代码:

public static EasingDoubleKeyFrame CreateEasingDoubleKeyFrame(
    double frameTimeInSeconds,double value) {

    //  Create double key frame.
    return new EasingDoubleKeyFrame() {
        KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(frameTimeInSeconds)),Value = value
    };
}

public static DoubleAnimationUsingKeyFrames BuildDoubleAnimationUsingKeyFrames(
    FillBehavior fillBehavior,DoubleKeyFrameCollection keyFrames,string targetName,PropertyPath targetProperty) {

    //  Create animation.
    var animation = new DoubleAnimationUsingKeyFrames();

    //  Set animation end behavior.
    animation.FillBehavior = fillBehavior;

    //  Set animation frames.
    animation.KeyFrames = keyFrames;

    //  Set animation target object.
    Storyboard.SetTargetName(animation,targetName);

    //  Set animation target property.
    Storyboard.SetTargetProperty(animation,targetProperty);

    return animation;
}

解决方法

您似乎将Storyboard的目标设置错误。

Storyboard.SetTargetName需要已注册的元素名称。

您必须选择:使用Storyboard.SetTarget或注册控件的名称。

解决方案1:Storyboard.SetTarget(推荐)

在C#中创建动画时,推荐的方法是使用Storyboard.SetTarget(而不是更方便的XAML)。 Storyboard.SetTargetName期望XAML名称范围内的一个元素,并使用FrameworkElement.Name指令设置了X:Name。使用Storyboard.SetTarget消除了将目标元素注册在名称范围内的要求。

StoryBoardsBuilder.cs

class StoryBoardsBuilder
{
  public static DoubleAnimationUsingKeyFrames BuildDoubleAnimationUsingKeyFrames(
    FillBehavior fillBehavior,DoubleKeyFrameCollection keyFrames,DependencyObject target,PropertyPath targetProperty) 
  {
    //  Create animation.
    var animation = new DoubleAnimationUsingKeyFrames();

    //  Set animation end behavior.
    animation.FillBehavior = fillBehavior;

    //  Set animation frames.
    animation.KeyFrames = keyFrames;

    //  Set animation target object.
    Storyboard.SetTarget(animation,target);

    //  Set animation target property.
    Storyboard.SetTargetProperty(animation,targetProperty);

    return animation;
  }
}

示例

class EventsPage 
{
    //  ...    

    public void AddEvent(Event @event) {
        var eventUC = new EventUserContrl(@event);
        eventUC.ExpandCollapseAnimation += ExpandCollapseAnimation;
    }

    private ExpandCollapseAnimation(EventUserControl eventUC,double height,double time) 
    {
        ...

        //  Create Animation.
        var heightSizeAnimation= StoryBoardsBuilder.BuildDoubleAnimationUsingKeyFrames(
                FillBehavior.Stop,frames,eventUC,new PropertyPath("Height"));

        ...
    }

    //  ...

}

解决方案2:Storyboard.SetTargetName

Storyboard.SetTargetName需要一个名为FrameworkElement的动画目标。此元素的名称必须在当前XAML名称范围内注册。使用x:Name指令在XAML中命名元素时,会自动完成此操作。
由于您决定使用C#创建元素,因此必须手动注册元素名称。如果没有活动的名称范围,则还必须手动创建一个新的名称范围。

最容易访问现有名称范围的是对已命名XAML元素的引用。在此元素上,调用FrameworkElement.RegisterName来注册元素。有关更多信息,请参见Microsoft Docs: Targeting Framework Elements,Framework Content Elements,and Freezables

class EventsPage 
{
    //  ...    

    public void AddEvent(Event @event) 
    {
        var eventUC = new EventUserContrl(@event);
        eventUC.Name = "MyEventUserContrl";

        // Register the element name in the current name scope manually 
        EventsStackPanel.RegisterName(eventUC.Name,eventUC);

        EventsStackPanel.Children.Add(eventUC);

        eventUC.ExpandCollapseAnimation += ExpandCollapseAnimation;
    }
}

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...