问题描述
我在运行.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;
}
}