WPF中自动增加行(动画)的TextBox
原文:WPF中自动增加行(动画)的TextBox
WPF中自动增加行(动画)的TextBox
WPF中的Textbox控件是可以自动换行的,只要设置TextWrapping属性为”Wrap”即可,但是存在一个问题:Textbox的高度是固定的,当输入文本过多时就会出现如下情况。
Textbox虽然没有自动增加高度的属性,但是我们可以通过设置来实现这一个功能。相关xaml代码如下
<Grid VerticalAlignment="Top" HorizontalAlignment="Left" Width="36" Height="100"><TextBox x:Name="textBox" TextWrapping="Wrap" VerticalAlignment="Top" /></Grid>
效果如下
这里需要注意的是
- 如果设置了textBox的Width、Height或者Margin属性,那么此textBox的大小就已经限制死了,不会自动增加,会出现上图中的情况。
- 如果想设置textBox的大小和位置,需要把textBox放在一个Grid中,通过Grid的属性来控制textBox(上文中xaml文件中的方法)
其实到此为止所需要的功能已经实现了,但是为了让让textbox更美观,我加了一个动画
效果如下:
表面上看是一个textbox,其实是一个Grid加上2个textBox(一个显示,一个隐藏),xaml代码如下
<Grid><TextBox x:Name="txtVisible" TextWrapping="Wrap"/><TextBox x:Name="txtHidden" TextWrapping="Wrap" Visibility="Hidden" VerticalAlignment="Top"/>
</Grid>
Grid是用来控制textbox的大小的,两个textbox中,显示的那个用于输入文字,隐藏的用于触发动画。原理如下
在txtVisible中输入文字的同时,txtVisible把text传递给txtHidden,当txtHidden中的内容已经满一行时,会触发SizeChange事件,这个事件再触发txtVisible高度变化动画。代码如下
public partial class txt : UserControl
{private HeightAnimation anim;private double _animationDuration;public txt(){InitializeComponent();// Initialize the animationanim = new HeightAnimation(this);AnimationDuration = 500; //default value// Add the handlers to the required eventstxtHidden.SizeChanged += TxtHidden_SizeChanged;txtVisible.TextChanged += TxtVisible_TextChanged;}/// <summary>/// Gets or sets a value indicating whether the control is animated on loaded./// </summary>public bool AnimateOnLoaded { get; set; } = false;/// <summary>/// Gets or sets a value indicating whether the control is animated./// </summary>public bool IsAnimated { get; set; } = true;/// <summary>/// Gets or sets the duration of the animation./// </summary>public double AnimationDuration{get { return _animationDuration; }set{_animationDuration = value;anim.Duration = new Duration(TimeSpan.FromMilliseconds(value));}}/// <summary>/// Gets or sets the text contents of the AnimatedTextBox./// </summary>public string Text{get { return txtHidden.Text; }set{txtHidden.Text = value;txtVisible.Text = value;}}private void TxtVisible_TextChanged(object sender, TextChangedEventArgs e){// When the user's writing in txtVisible, we copy the text to txtHiddentxtHidden.Text = txtVisible.Text;}private void TxtHidden_SizeChanged(object sender, SizeChangedEventArgs e){OnHeightChanged(e.PreviousSize.Height, e.NewSize.Height);}/// <summary>/// To execute when the txtHidden's Height has changed./// </summary>private void OnHeightChanged(double previousHeight, double newHeight){//Animation type, increase txtVisible's height or decreaseanim.ChangeType = (newHeight > previousHeight) ? HeightAnimation.ChangeTypes.Increased : HeightAnimation.ChangeTypes.Decreased;// Animate the Height from the txtHidden's previousHeight to its newHeightanim.From = previousHeight;anim.To = newHeight;// Start the animationanim.BeginAnimation();}/// <summary>/// Manages the AnimatedTextBox Height's animation./// </summary>private class HeightAnimation{private Storyboard sb;private DoubleAnimation anim;private double _from;private double _to;private Duration _duration;private FrameworkElement _fe;private ChangeTypes _changeType;/// <summary>/// The possible types of the Height change./// </summary>public enum ChangeTypes{Increased,Decreased}/// <summary>/// Constructor of the class./// </summary>public HeightAnimation(FrameworkElement fe){// Set the FrameworkElement which manages the animation_fe = fe;// Initialize the Storyboardsb = new Storyboard();sb.AutoReverse = false;// Initialize the animationanim = new DoubleAnimation();anim.Name = "anim";// Set the EasingFunction on a new instance of CubicEase whose EasingMode is EaseInOutanim.EasingFunction = new CubicEase() { EasingMode = EasingMode.EaseInOut };// Bind the Animation with the txtVisible TextBoxStoryboard.SetTargetName(anim, "txtVisible");// Add the animation to the Storyboard's childrensb.Children.Add(anim);}/// <summary>/// Gets or sets the type of the Height change./// </summary>public ChangeTypes ChangeType{get { return _changeType; }set{_changeType = value;/* If the Height has inreased, set the target property to MaxHeight, else to MinHeight* (instead of animating directly the Height, we animate MaxHeight/MinHeight to prevent the AnimatedTextBox* from growing/shrinking suddenly) */Storyboard.SetTargetProperty(anim, new PropertyPath(string.Format("(TextBox.{0})", (value == ChangeTypes.Increased) ? "MaxHeight" : "MinHeight")));}}/// <summary>/// Gets or sets the animation's starting Height./// </summary>public double From{get { return _from; }set{_from = value;anim.From = value;}}/// <summary>/// Gets or sets the animation's ending Height./// </summary>public double To{get { return _to; }set{_to = value;anim.To = value;}}/// <summary>/// Gets or sets the animation's duration./// </summary>public Duration Duration{get { return _duration; }set{_duration = value;anim.Duration = value;}}/// <summary>/// Begins the animation./// </summary>public void BeginAnimation(){_fe.BeginStoryboard(sb);}}
}
posted on 2019-01-15 17:08 NET未来之路 阅读(...) 评论(...) 编辑 收藏