使用Storyboard动画后无法拖动GridSplitter

VBProFan 2017-08-29 04:08:09


程序运行起来后界面如图,蓝块和红块之间有个GridSplitter,用鼠标左右拖动可以调整左右两块的大小。点击蓝块左侧的按钮后鼠标移到GridSplitter的位置仍然会变为左右箭头的指针,但是无法再调整大小,为什么?

MainWindow.xaml:

<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20"/>
<ColumnDefinition x:Name="MenuList" Width="*"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>

<Button Name="cmd"
Grid.Column="0"
Click="Button_Click" />

<TextBlock Grid.Column="1"
Background="Blue" />

<GridSplitter
Grid.Column="2"
Width="3"
HorizontalAlignment="Stretch"
DragCompleted="GridSplitter_DragCompleted" />

<TextBlock Grid.Column="3"
Background="Red" />
</Grid>
</Window>


MainWindow.xaml.cs:
using System;
using System.Windows;
using System.Windows.Media.Animation;

namespace WpfApp1
{
public partial class MainWindow : Window
{
int PanelWidth = 200;
public MainWindow()
{
InitializeComponent();
MenuList.Width = new GridLength(PanelWidth);
}
private void slideSubMenu(DependencyObject animateObject, GridLength from, GridLength to)
{
Storyboard storyboard = new Storyboard();
GridLengthAnimation widthAnimation = new GridLengthAnimation()
{
From = from,
To = to,
Duration = new Duration(TimeSpan.FromSeconds(0.3))
};
Storyboard.SetTarget(widthAnimation, animateObject);
Storyboard.SetTargetProperty(widthAnimation, new PropertyPath("(Width)"));
storyboard.Children.Add(widthAnimation);
storyboard.Begin();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
bool bSubMenuVisible = (MenuList.Width == new GridLength(PanelWidth));
double toGridLength = bSubMenuVisible ? 0 : PanelWidth;

slideSubMenu(MenuList, MenuList.Width, new GridLength(toGridLength));
//如果屏蔽上面那句,启用下面那句,则 GridSplitter 能正常拖动
//MenuList.Width = new GridLength(toGridLength);
}

private void GridSplitter_DragCompleted(object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e)
{
PanelWidth = (int)MenuList.ActualWidth;
}
}
}



GridLengthAnimation.cs:
using System;
using System.Windows;
using System.Windows.Media.Animation;

namespace WpfApp1
{
public class GridLengthAnimation : AnimationTimeline
{
public override Type TargetPropertyType => typeof(GridLength);

protected override Freezable CreateInstanceCore()
{
return new GridLengthAnimation();
}

public static readonly DependencyProperty FromProperty = DependencyProperty.Register("From", typeof(GridLength), typeof(GridLengthAnimation));

public GridLength From
{
get
{
return (GridLength)GetValue(FromProperty);
}
set
{
SetValue(FromProperty, value);
}
}

public static readonly DependencyProperty ToProperty = DependencyProperty.Register("To", typeof(GridLength), typeof(GridLengthAnimation));

public GridLength To
{
get
{
return (GridLength)GetValue(ToProperty);
}
set
{
SetValue(ToProperty, value);
}
}

public const string EasingFunctionPropertyName = "EasingFunction";

public IEasingFunction EasingFunction
{
get
{
return (IEasingFunction)GetValue(EasingFunctionProperty);
}
set
{
SetValue(EasingFunctionProperty, value);
}
}

public static readonly DependencyProperty EasingFunctionProperty = DependencyProperty.Register(
EasingFunctionPropertyName,
typeof(IEasingFunction),
typeof(GridLengthAnimation),
new UIPropertyMetadata(null));

public override object GetCurrentValue(object defaultOriginValue, object defaultDestinationValue, AnimationClock animationClock)
{
double fromVal = ((GridLength)GetValue(FromProperty)).Value;
double toVal = ((GridLength)GetValue(ToProperty)).Value;
double progress = animationClock.CurrentProgress.Value;

IEasingFunction easingFunction = EasingFunction;
if (easingFunction != null)
{
progress = easingFunction.Ease(progress);
}

if (fromVal > toVal)
{
progress = 1 - progress;
}

double v = progress * Math.Abs(fromVal - toVal) + Math.Min(fromVal, toVal);
return new GridLength(v, GridUnitType.Pixel);
}
}
}
...全文
185 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
VBProFan 2017-08-30
  • 打赏
  • 举报
回复
如果是加 Storyboard.SetTarget(null, animateObject); 则发生运行时错误:值不能为null
VBProFan 2017-08-30
  • 打赏
  • 举报
回复
引用 1 楼 Libby1984 的回复:
你如果为某个控件的某个属性应用了动画,动画执行后如果想在代买修改那个属性才值,必须要接触动画的绑定。如果你为GridSplitter的Width属性绑定了动画,可以用这样:GridSplitter.BeginAnimation(FrameworkElement.WidthProperty, null); 然后就可以修改宽度的值。
谢谢!这思路听起来很有道理,我试着在 storyboard.Begin(); 后加了一句 MenuList.BeginAnimation(WidthProperty, null); 还是不行。不过已经有研究的方向了,再次感谢!
  • 打赏
  • 举报
回复
你如果为某个控件的某个属性应用了动画,动画执行后如果想在代买修改那个属性才值,必须要接触动画的绑定。如果你为GridSplitter的Width属性绑定了动画,可以用这样:GridSplitter.BeginAnimation(FrameworkElement.WidthProperty, null); 然后就可以修改宽度的值。
  • 打赏
  • 举报
回复
引用 2 楼 VBProFan 的回复:
[quote=引用 1 楼 Libby1984 的回复:] 你如果为某个控件的某个属性应用了动画,动画执行后如果想在代买修改那个属性才值,必须要接触动画的绑定。如果你为GridSplitter的Width属性绑定了动画,可以用这样:GridSplitter.BeginAnimation(FrameworkElement.WidthProperty, null); 然后就可以修改宽度的值。
谢谢!这思路听起来很有道理,我试着在 storyboard.Begin(); 后加了一句 MenuList.BeginAnimation(WidthProperty, null); 还是不行。不过已经有研究的方向了,再次感谢![/quote] 你试试用MenuList.BeginAnimation启动动画,结束后用MenuList.BeginAnimation设置为空
VBProFan 2017-08-30
  • 打赏
  • 举报
回复
搞定! 增加: widthAnimation.FillBehavior = FillBehavior.Stop; 恢复: MenuList.Width = new GridLength(toGridLength); 参看: https://msdn.microsoft.com/zh-cn/library/aa970493.aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-4

8,735

社区成员

发帖
与我相关
我的任务
社区描述
WPF/Silverlight相关讨论
社区管理员
  • WPF/Silverlight社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧