有没有什么办法可以从XAML生成栅格列宽或栅格行高?在XAML中动画网格列或网格行?
回答
ColumnDefinition.Width
和RowDefinition.Height
属性类型为GridLength
,并且此类型没有内置动画。所以如果你想这样做,你可能需要创建自己的GridLengthAnimation
类。这可能不是太不可能的,如果你把DoubleAnimation
作为一个例子,但也不容易......
编辑:实际上,有几个有趣的结果,如果你搜索在谷歌“GridLength动画” ......
http://windowsclient.net/learn/video.aspx?v=70654
http://marlongrech.wordpress.com/2007/08/20/gridlength-animation/
http://www.codeproject.com/KB/WPF/GridLengthAnimation.aspx
我累了具有XAML拨弄动画网格的行和列前一阵子,所以我写了一对夫妇的方法从代码完全做到这一点。
有了这些,你可以展开/从代码一行收缩列和行:
Animation.AnimationHelper.AnimateGridColumnExpandCollapse(LeftColumn, true, expandedHeight, currentWidth, LeftColumn.MinWidth, 0, 200);
一个重要的事情要注意的是在完成动画设置为NULL。如果不这样做,动画完成后,网格仍处于动画的控制之下。如果网格没有分割器,这可能没问题,但是如果网格有分割器,并且您希望能够在动画完成后手动调整它,那么必须在动画完成后将动画设置为空。
这里是方法:
/// <summary>
/// Animate expand/collapse of a grid column.
/// </summary>
/// <param name="gridColumn">The grid column to expand/collapse.</param>
/// <param name="expandedWidth">The expanded width.</param>
/// <param name="milliseconds">The milliseconds component of the duration.</param>
/// <param name="collapsedWidth">The width when collapsed.</param>
/// <param name="minWidth">The minimum width of the column.</param>
/// <param name="seconds">The seconds component of the duration.</param>
/// <param name="expand">If true, expand, otherwise collapse.</param>
public static void AnimateGridColumnExpandCollapse(ColumnDefinition gridColumn, bool expand, double expandedWidth, double collapsedWidth,
double minWidth, int seconds, int milliseconds)
{
if(expand && gridColumn.ActualWidth >= expandedWidth)
// It's as wide as it needs to be.
return;
if (!expand && gridColumn.ActualWidth == collapsedWidth)
// It's already collapsed.
return;
Storyboard storyBoard = new Storyboard();
GridLengthAnimation animation = new GridLengthAnimation();
animation.From = new GridLength(gridColumn.ActualWidth);
animation.To = new GridLength(expand ? expandedWidth : collapsedWidth);
animation.Duration = new TimeSpan(0, 0, 0, seconds, milliseconds);
// Set delegate that will fire on completion.
animation.Completed += delegate
{
// Set the animation to null on completion. This allows the grid to be resized manually
gridColumn.BeginAnimation(ColumnDefinition.WidthProperty, null);
// Set the final value manually.
gridColumn.Width = new GridLength(expand ? expandedWidth : collapsedWidth);
// Set the minimum width.
gridColumn.MinWidth = minWidth;
};
storyBoard.Children.Add(animation);
Storyboard.SetTarget(animation, gridColumn);
Storyboard.SetTargetProperty(animation, new PropertyPath(ColumnDefinition.WidthProperty));
storyBoard.Children.Add(animation);
// Begin the animation.
storyBoard.Begin();
}
/// <summary>
/// Animate expand/collapse of a grid row.
/// </summary>
/// <param name="gridRow">The grid row to expand/collapse.</param>
/// <param name="expandedHeight">The expanded height.</param>
/// <param name="collapsedHeight">The collapesed height.</param>
/// <param name="minHeight">The minimum height.</param>
/// <param name="milliseconds">The milliseconds component of the duration.</param>
/// <param name="seconds">The seconds component of the duration.</param>
/// <param name="expand">If true, expand, otherwise collapse.</param>
public static void AnimateGridRowExpandCollapse(RowDefinition gridRow, bool expand, double expandedHeight, double collapsedHeight, double minHeight, int seconds, int milliseconds)
{
if (expand && gridRow.ActualHeight >= expandedHeight)
// It's as high as it needs to be.
return;
if (!expand && gridRow.ActualHeight == collapsedHeight)
// It's already collapsed.
return;
Storyboard storyBoard = new Storyboard();
GridLengthAnimation animation = new GridLengthAnimation();
animation.From = new GridLength(gridRow.ActualHeight);
animation.To = new GridLength(expand ? expandedHeight : collapsedHeight);
animation.Duration = new TimeSpan(0, 0, 0, seconds, milliseconds);
// Set delegate that will fire on completioon.
animation.Completed += delegate
{
// Set the animation to null on completion. This allows the grid to be resized manually
gridRow.BeginAnimation(RowDefinition.HeightProperty, null);
// Set the final height.
gridRow.Height = new GridLength(expand ? expandedHeight : collapsedHeight);
// Set the minimum height.
gridRow.MinHeight = minHeight;
};
storyBoard.Children.Add(animation);
Storyboard.SetTarget(animation, gridRow);
Storyboard.SetTargetProperty(animation, new PropertyPath(RowDefinition.HeightProperty));
storyBoard.Children.Add(animation);
// Begin the animation.
storyBoard.Begin();
}
我建立在由佰肖提供的AnimationHelper
类和包裹在可重复使用的GridAnimationBehavior
其可附接至RowDefinition
和ColumnDefinition
元件。
/// <summary>
/// Wraps the functionality provided by the <see cref="AnimationHelper"/> class
/// in a behavior which can be used with the <see cref="ColumnDefinition"/>
/// and <see cref="RowDefinition"/> types.
/// </summary>
public class GridAnimationBehavior : DependencyObject
{
#region Attached IsExpanded DependencyProperty
/// <summary>
/// Register the "IsExpanded" attached property and the "OnIsExpanded" callback
/// </summary>
public static readonly DependencyProperty IsExpandedProperty =
DependencyProperty.RegisterAttached("IsExpanded", typeof(bool), typeof(GridAnimationBehavior),
new FrameworkPropertyMetadata(OnIsExpandedChanged));
public static void SetIsExpanded(DependencyObject dependencyObject, bool value)
{
dependencyObject.SetValue(IsExpandedProperty, value);
}
#endregion
#region Attached Duration DependencyProperty
/// <summary>
/// Register the "Duration" attached property
/// </summary>
public static readonly DependencyProperty DurationProperty =
DependencyProperty.RegisterAttached("Duration", typeof(TimeSpan), typeof(GridAnimationBehavior),
new FrameworkPropertyMetadata(TimeSpan.FromMilliseconds(200)));
public static void SetDuration(DependencyObject dependencyObject, TimeSpan value)
{
dependencyObject.SetValue(DurationProperty, value);
}
private static TimeSpan GetDuration(DependencyObject dependencyObject)
{
return (TimeSpan)dependencyObject.GetValue(DurationProperty);
}
#endregion
#region GridCellSize DependencyProperty
/// <summary>
/// Use a private "GridCellSize" dependency property as a temporary backing
/// store for the last expanded grid cell size (row height or column width).
/// </summary>
private static readonly DependencyProperty GridCellSizeProperty =
DependencyProperty.Register("GridCellSize", typeof(double), typeof(GridAnimationBehavior),
new UIPropertyMetadata(0.0));
private static void SetGridCellSize(DependencyObject dependencyObject, double value)
{
dependencyObject.SetValue(GridCellSizeProperty, value);
}
private static double GetGridCellSize(DependencyObject dependencyObject)
{
return (double)dependencyObject.GetValue(GridCellSizeProperty);
}
#endregion
/// <summary>
/// Called when the attached <c>IsExpanded</c> property changed.
/// </summary>
private static void OnIsExpandedChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
var duration = GetDuration(dependencyObject);
var rowDefinition = dependencyObject as RowDefinition;
if (rowDefinition != null)
{
// The IsExpanded attached property of a RowDefinition changed
if ((bool)e.NewValue)
{
var expandedHeight = GetGridCellSize(rowDefinition);
if (expandedHeight > 0)
{
// Animate row height back to saved expanded height.
AnimationHelper.AnimateGridRowExpandCollapse(rowDefinition, true, expandedHeight, rowDefinition.ActualHeight, 0, duration);
}
}
else
{
// Save expanded height and animate row height down to zero.
SetGridCellSize(rowDefinition, rowDefinition.ActualHeight);
AnimationHelper.AnimateGridRowExpandCollapse(rowDefinition, false, rowDefinition.ActualHeight, 0, 0, duration);
}
}
var columnDefinition = dependencyObject as ColumnDefinition;
if (columnDefinition != null)
{
// The IsExpanded attached property of a ColumnDefinition changed
if ((bool)e.NewValue)
{
var expandedWidth = GetGridCellSize(columnDefinition);
if (expandedWidth > 0)
{
// Animate column width back to saved expanded width.
AnimationHelper.AnimateGridColumnExpandCollapse(columnDefinition, true, expandedWidth, columnDefinition.ActualWidth, 0, duration);
}
}
else
{
// Save expanded width and animate column width down to zero.
SetGridCellSize(columnDefinition, columnDefinition.ActualWidth);
AnimationHelper.AnimateGridColumnExpandCollapse(columnDefinition, false, columnDefinition.ActualWidth, 0, 0, duration);
}
}
}
}
注意,我调整Nigel的码比特以使用型时间跨度的参数为动画的持续时间,而不是独立的秒和毫秒参数。
此行为使网格行/列MVVM友好的动画(仅XAML,没有后面的代码需要)。示例:
<Grid.RowDefinitions>
<RowDefinition Height="*" Behaviors:GridAnimationBehavior.IsExpanded="{Binding IsUpperPaneVisible}" />
<RowDefinition Height="*" />
<RowDefinition Height="*" Behaviors:GridAnimationBehavior.IsExpanded="{Binding IsLowerPaneVisible}" />
</Grid.RowDefinitions>
我添加了此答案,因为原始海报要求提供纯XAML解决方案。
工作情况如何?为什么不在你想要动画的特定行内放置一个网格(或任何其他所需的控件),将行高设置为“Auto”,然后为控件的高度设置动画。它为我工作。
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Button x:Name="ExpandCollapseBtn" Width="100" Click="ExpandCollapse_Click"/>
<WrapPanel x:Name="ToolBox" Grid.Row="1" Height="0">
<Button Content="1" Width="50" Height="50"/>
<Button Content="2" Width="50" Height="50"/>
<Button Content="3" Width="50" Height="50"/>
<Button Content="4" Width="50" Height="50"/>
</WrapPanel>
</Grid>
后面的代码:
private bool Expanded = false;
void ExpandCollapse_Click(object sender, RoutedEventArgs e)
{
if (Expanded)
{
var anim = new DoubleAnimation(0, (Duration)TimeSpan.FromSeconds(0.3));
anim.Completed += (s, _) => Expanded = false;
ToolBox.BeginAnimation(ContentControl.HeightProperty, anim);
}
else
{
var anim = new DoubleAnimation(100, (Duration)TimeSpan.FromSeconds(0.3));
anim.Completed += (s, _) => Expanded = true;
ToolBox.BeginAnimation(ContentControl.HeightProperty, anim);
}
}
我承认它不是你在找什么。但它是一个快速解决方案(当然,假设最终你希望UIElement放置在通过网格行动画生成动画的网格中)。你可以同样做它的列宽。
这是迄今为止最简单的方法......工作得非常好,代码/麻烦最少。 – AshbyEngineer 2014-07-13 17:42:09
MahApps.Metro库有一个内置的控制。来源可以发现here。
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="48" x:Name="HamburgerMenuColumn" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.Resources>
<Storyboard x:Key="CloseMenu" Storyboard.TargetName="HamburgerMenuColumn" Storyboard.TargetProperty="(ColumnDefinition.Width)">
<metro:GridLengthAnimation To="48" Duration="00:00:00"></metro:GridLengthAnimation>
</Storyboard>
</Grid.Resources>
</Grid>
- 1. WPF - 在XAML中动画网格长度
- 2. XAML网格列宽
- 3. 在网格中显示XAML
- 4. 可以在整个网格中移动且不属于网格行或列的XAML元素
- 5. Xaml动态网格与Viewmodels
- 6. XAML C#隐藏网格行
- 7. 将网格划分为网格XAML
- 8. 网格进度条或动画
- 9. XAML网格布局
- 10. XAML网格布局
- 11. XAML:我可以通过名称引用网格行或列吗?
- 12. 画在网格上
- 13. vuejs动画列表内网格项目
- 14. Three.js网格不AnimationHandler动画
- 15. CSS3 - 动画精灵网格
- 16. Threejs克隆网格动画
- 17. Flash网格补间/动画
- 18. 动画网格行高度变化WP
- 19. 如何在WPF/XAML中滚动网格行?
- 20. 如何在XAML中将网格浮动到另一个网格上方Windows8
- 21. 动态网格列
- 22. Xaml替代网格布局
- 23. WPF XAML绑定网格
- 24. WPF网格XAML布局
- 25. XAML数据网格的DataTemplate
- 26. 如何统一网格的行或列
- 27. Recyclerview带备用1列网格行和2列网格行
- 28. XAML:网格单元格溢出
- 29. 如何防止Silverlight xaml网格中的某列占据整行?
- 30. 动画Open GL ES中的网格
第一个链接帮助我分配,谢谢:) – 2012-04-12 05:11:17
Annnd ...“windowsclient.net”链接被破坏。看起来好像MS在Win8之前拆除任何东西,或者使用Hanlon的Razor,根本不在意它。 – codekaizen 2012-12-10 20:39:16
第一个链接[由Wayback Machine保存](http://web.archive.org/web/20111201124746/http://windowsclient.net/learn/video.aspx?v=70654) – fernio 2017-03-16 20:44:43