我正在尝试重新创建Windows Phone连续体转换(一个选定的项目圈出来并进入视图,例如在邮件客户端中打开电子邮件时),我似乎无法让一个动画工作
当您返回项目列表时,之前选择的项目必须从左上角的某处滑回到列表中。我想我会保留对所选项的引用,然后在页面的Loaded事件处理程序中,检查该引用是否为null,如果是,则创建一个storyboard,找到正确的列表框项,将其设置为动画的目标,并运行它。
但是,这不起作用。这是listbox itemtemplate:
<StackPanel x:Name="commuteStackPanel" local:TiltEffect.IsTiltEnabled="True" Margin="0,0,0,38" Tap="StackPanel_Tap">
<TextBlock Style="{StaticResource PhoneTextTitle3Style}" TextTrimming="WordEllipsis" Text="{Binding Title}" />
<TextBlock Style="{StaticResource PhoneTextSubtleStyle}" Text="{Binding SelectedDays}" Margin="12,0,12,0"/>
</StackPanel>
这是动画,定义为页面资源:
<Storyboard xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" x:Key="continuumStoryboard">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateX)" >
<EasingDoubleKeyFrame KeyTime="0" Value="-70"/>
<EasingDoubleKeyFrame KeyTime="0:0:4.15" Value="0">
<EasingDoubleKeyFrame.EasingFunction>
<ExponentialEase EasingMode="EaseOut" Exponent="3"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)" >
<EasingDoubleKeyFrame KeyTime="0" Value="-30"/>
<EasingDoubleKeyFrame KeyTime="0:0:4.15" Value="0">
<EasingDoubleKeyFrame.EasingFunction>
<ExponentialEase EasingMode="EaseOut" Exponent="3"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
这是页面的代码隐藏:
private FrameworkElement lastSelectedElement = null;
private void StackPanel_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
this.lastSelectedElement = sender as FrameworkElement;
}
private void page_Loaded(object sender, RoutedEventArgs e)
{
if (this.lastSelectedElement != null)
{
// Using the last selected element's datacontext, find the relevant ListBoxItem
var listBoxItem = commutesListBox.ItemContainerGenerator.ContainerFromItem(this.lastSelectedElement.DataContext);
// Get the actual stackpanel we want to animate
var element = FindVisualChild<StackPanel>(listBoxItem);
// Ensure it has the proper transforms
element.RenderTransform = new CompositeTransform { TranslateX = 0, TranslateY = 0 };
// Get the storyboard and make sure it is not playing.
var storyboard = Resources["continuumStoryboard"] as Storyboard;
storyboard.Stop();
// Set the stackpanel as the target for each timeline in the storyboard
foreach (var timeline in storyboard.Children)
{
Storyboard.SetTarget(timeline, element);
}
// Play the animation.
storyboard.Begin();
}
}
我从MSDN文章中复制的FindVisualChild方法:
private childItem FindVisualChild<childItem>(DependencyObject obj)
where childItem : DependencyObject
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
if (child != null && child is childItem)
return (childItem)child;
else
{
childItem childOfChild = FindVisualChild<childItem>(child);
if (childOfChild != null)
return childOfChild;
}
}
return null;
}
然而,这不起作用。如果我设置任何其他元素,例如列表框本身,作为动画的目标,我可以看到它正在播放,但是当我设置datatemplate中的任何元素时,没有任何反应。没有错误,没有。
我想我会尝试并尝试通过替换
来动画列表框的第一项this.lastSelectedElement.DataContext
与
commutesListBox.Items.First()
但仍然没有骰子。我在这里缺少什么?
编辑我已经设法让动画运行,但我仍然不明白为什么。事实证明,在Loaded事件中,viewmodel将重新填充列表框绑定的ObservableCollection。在阻止这种情况发生之后,动画就会播放。
我没有得到的是,即使您没有对绑定值或datacontext执行任何操作,问题仍然存在,而是使用Items.First()。即使viewmodel发生了变化,它仍然应该有一个First()项目(并逐步显示它确实存在)。
答案 0 :(得分:1)
嗯,我用你的代码构建了一个简单的应用程序(你可以downlad it here),所有东西都应该按照我的想法进行(我认为)。在我的应用程序中:
可能问题在于您的page_Loaded
事件被触发的时间 - 您必须先在代码中点按StackPanel
,当Page加载时,用户没有机会点击项目。