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 animation
        anim = new HeightAnimation(this);
        AnimationDuration = 500; //default value

        // Add the handlers to the required events
        txtHidden.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 txtHidden
        txtHidden.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 decrease
        anim.ChangeType = (newHeight > previousHeight) ? HeightAnimation.ChangeTypes.Increased : HeightAnimation.ChangeTypes.Decreased;

        // Animate the Height from the txtHidden's previousHeight to its newHeight
        anim.From = previousHeight;
        anim.To = newHeight;

        // Start the animation
        anim.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 Storyboard
            sb = new Storyboard();
            sb.AutoReverse = false;

            // Initialize the animation
            anim = new DoubleAnimation();
            anim.Name = "anim";

            // Set the EasingFunction on a new instance of CubicEase whose EasingMode is EaseInOut
            anim.EasingFunction = new CubicEase() { EasingMode = EasingMode.EaseInOut };

            // Bind the Animation with the txtVisible TextBox
            Storyboard.SetTargetName(anim, "txtVisible");

            // Add the animation to the Storyboard's children
            sb.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);
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值