自动适应输入内容宽度的TextBox控件

简介:

在ASP.NET的上面,TextBox是表单设计时最常用的控件之一。很多时候为了页面的紧凑和美观,我们需要适当的限制TextBox的显示宽度,但是如果TextBox过于窄了之后,又会给用户的填写带了不便,而且更麻烦的是很多时候我们并不知道用户到底会往那个TextBox里填多少内容。为了解决这些问题,下面给大家推荐一个可自动适应输入内容的宽度的TextBox控件。

    本控件是从TextBox控件继承,设计原理是使用一个agent input(type=text)来做为实际的用户录入的TextBox,在焦点切换的过程中完成background input和agent input的属性同步。 

    下面的代码完成两个input之间的样式和属性同步:

function ATB_SwitchToInputAgent(input) 
    注意:不能使用style=style或for( attribute in style)的方式来赋值,否这引起onpropertychange的死循环递归

    第二个问题是使用onpropertychange属性来同步agent input的宽度和其内容宽度相等,代码如下: 
function ATB_AutoIncreaseWidth(input) 

     if ( input.style.display == 'none' )  return
     var spanWrapper = input.parentElement; 
     var userInput = spanWrapper.firstChild; 
    userInput.value = input.value; 
     var absOffsetWidth = GetAbsoluteOffsetLeft(input); 
     var docClientWidth = window.document.body.clientWidth; 
     if ( input.scrollWidth < userInput.clientWidth ) 
    { 
         if ( absOffsetWidth + styleWidth >= docClientWidth )  
        { 
            input.style.width = docClientWidth - absOffsetWidth; 
        } 
         else 
        { 
            input.style.width = userInput.clientWidth+2; 
        } 
         return
    } 
     var styleWidth = parseInt(input.style.width); 
     if ( styleWidth != input.scrollWidth+2 ) 
    { 
         if ( absOffsetWidth + styleWidth >= docClientWidth )  
        { 
            input.style.width = docClientWidth - absOffsetWidth; 
        } 
         else 
        { 
            input.style.width = input.scrollWidth+2; 
        } 
    } 
    这里需要注意的是当增长的agent input的最右端超出了IE的body区域时,需要停止其增长,否则用户看不见输入的东西了。 

    演示效果如下:
    
*

#region 附 AdjustableTextBox 控件源码
using System;
using System.IO;
using System.Drawing;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;

namespace WebExcel.UI.WebControls
{
     ///   <summary>
    
///  Summary description for AdjustableTextBox.
    
///   </summary>
    [DefaultProperty("Text")]
    [ToolboxData("<{0}:AdjustableTextBox runat=server></{0}:AdjustableTextBox>")]
     public  class AdjustableTextBox : TextBox
    {
         public Color AgentBorderColor
        {
             get
            {
                 object obj = ViewState["AgentBorderColor"];
                 return obj ==  null ? Color.Gray : (Color)obj;
            }
             set
            {
                ViewState["AgentBorderColor"] = value;
            }
        }

         public  bool AutoIncrease
        {
             get
            {
                 object obj = ViewState["AutoIncrease"];
                 return obj ==  null ?  true : ( bool)obj;
            }
             set
            {
                ViewState["AutoIncrease"] = value;
            }
        }

         //  the property is always TextBoxMode.SingleLine.
         public  override TextBoxMode TextMode
        {
             get
            {
                 return  base.TextMode;
            }
             set
            {
                 base.TextMode = value;
                 if ( value != TextBoxMode.SingleLine )
                {
                     this.AutoIncrease =  false;
                }
                 else
                {
                     this.AutoIncrease =  true;
                }
            }
        }

         public  new Unit BorderWidth
        {
             get
            {
                 if (  base.BorderWidth == Unit.Empty )
                {
                     base.BorderWidth = 1;
                }
                 return  base.BorderWidth;
            }
             set
            {
                 if ( value != Unit.Empty )
                {
                     base.BorderWidth = value;
                }
            }
        }

         ///   <summary>  
        
///  Render this control to the output parameter specified.
        
///   </summary>
        
///   <param name="output">  The HTML writer to write out to  </param>
         protected  override  void Render(HtmlTextWriter output)
        {
             if (  this.AutoIncrease )
            {
                 this.RegisterClientScript();
                 base.Attributes["onfocus"] = "ATB_SwitchToInputAgent(this)";
                 base.Attributes.CssStyle["position"] = "relative";
                 if (  base.BorderWidth == Unit.Empty )
                {
                     base.BorderWidth = 1;
                }
                 string spanWrapper = @"<span style='z-index: 1; position: relative; border: solid 0px black;'>{0}<input type='text' onblur='ATB_GetAgentValue(this)' onpropertychange='ATB_AutoIncreaseWidth(this)' style='border: solid 1px gray; position: absolute; display:none;' /></span>";
                StringBuilder sb =  new StringBuilder();
                StringWriter sw =  new StringWriter(sb);
                HtmlTextWriter htw =  new HtmlTextWriter(sw);
                 base.Render(htw);
                output.Write( string.Format(spanWrapper, sb.ToString(), ColorTranslator.ToHtml( this.AgentBorderColor)));
            }
             else
            {
                 //  base.Attributes["onfocus"] = "this.height='100%'";
                 base.Render(output);
            }
        }

         private  void RegisterClientScript()
        {
             const  string COMMON_SCRIPT_KEY = "__CommonJavaScript__";
             string strCommon = @"<script language='javascript'>
            function GetAbsoluteOffsetLeft(element)
            {
                 if ( element ==  null || arguments.length != 1 )
                {
                     return;
                }
                var offsetLeft = element.offsetLeft;
                 while( element = element.offsetParent )
                {
                    offsetLeft += element.offsetLeft;
                }
                 return offsetLeft;
            }
            </script>";
             if ( ! this.Page.IsStartupScriptRegistered(COMMON_SCRIPT_KEY) )
            {
                 this.Page.RegisterStartupScript(COMMON_SCRIPT_KEY, strCommon);
            }

             const  string SCRIPT_KEY = "__AdjustableTextBoxKey__";
             string strScript = @"
                <script language='javascript'>
                function ATB_SwitchToInputAgent(input)
                {
                     if ( input.disabled )  return;
                    var spanWrapper = input.parentElement;
                    var agentInput = spanWrapper.lastChild;
                    var userOffsetTop, userOffsetLeft;
                    with(input.style)
                    {
                        var userMarginTop = parseInt(marginTop);
                        var userMarginLeft = parseInt(marginLeft);
                        var userBorderTop = parseInt(borderTopWidth);
                        var userBorderLeft = parseInt(borderLeftWidth);
                        userMarginTop = isNaN(userMarginTop) ? 0 : userMarginTop;
                        userMarginLeft = isNaN(userMarginLeft) ? 0 : userMarginLeft;
                        userBorderTop = isNaN(userBorderTop) ? 0 : userBorderTop;
                        userBorderLeft = isNaN(userBorderLeft) ? 0 : userBorderLeft;
                        userOffsetTop = userBorderTop + userMarginTop;
                        userOffsetLeft = userBorderLeft + userMarginLeft;
                    }
                    var retouch = 0;
                    agentInput.value = input.value;  //  must be mdified at first
                    agentInput.style.top = userOffsetTop;
                    agentInput.style.left = userOffsetLeft-1;
                    spanWrapper.style.zIndex = 10;
                    agentInput.style.display = 'inline';
                    agentInput.style.borderWdith = input.style.borderWdith;
                    agentInput.style.borderColor = input.style.borderColor;
                    agentInput.style.backgroundColor = input.style.backgroundColor;
                    agentInput.style.color = input.style.color;
                    agentInput.style.fontFamily = input.style.fontFamily;
                    agentInput.style.fontWegith = input.style.fontWeight;
                    agentInput.style.fontSize = input.style.fontSize;
                    agentInput.style.height = input.style.height;
                    var absOffsetWidth = GetAbsoluteOffsetLeft(input);
                    var docClientWidth = window.document.body.clientWidth;
                    var styleWidth = parseInt(agentInput.style.width);
                     if ( absOffsetWidth + styleWidth >= docClientWidth ) 
                    {
                        agentInput.style.width = docClientWidth - absOffsetWidth;
                    }
                     else
                    {
                        agentInput.style.width = input.clientWidth+2;
                    }
                    agentInput.style.fontStyle = input.style.fontStyle;
                     try { agentInput.style.font = input.style.font }  catch(exp){};
                    agentInput.style.fontVariant = input.style.fontVariant;
                    agentInput.style.zoom = input.style.zoom;
                    agentInput.readOnly = input.readOnly;
                     // agentInput.focus(); must remove!!!
                     if ( !agentInput.readOnly )
                    {        
                        agentInput.select();
                    }
                }

                function ATB_GetAgentValue(input)
                {
                    var spanWrapper = input.parentElement;
                    var userInput = spanWrapper.firstChild;
                    input.style.width = userInput.clientWidth+2;
                    spanWrapper.style.zIndex = 1;
                    userInput.value = input.value;
                    input.style.display = 'none';
                }
                
                function ATB_AutoIncreaseWidth(input)
                {
                     if ( input.style.display == 'none' )  return;
                    var spanWrapper = input.parentElement;
                    var userInput = spanWrapper.firstChild;
                    userInput.value = input.value;
                    var absOffsetWidth = GetAbsoluteOffsetLeft(input);
                    var docClientWidth = window.document.body.clientWidth;
                     if ( input.scrollWidth < userInput.clientWidth )
                    {
                         if ( absOffsetWidth + styleWidth >= docClientWidth ) 
                        {
                            input.style.width = docClientWidth - absOffsetWidth;
                        }
                         else
                        {
                            input.style.width = userInput.clientWidth+2;
                        }
                         return;
                    }
                    var styleWidth = parseInt(input.style.width);
                     if ( styleWidth != input.scrollWidth+2 )
                    {
                         if ( absOffsetWidth + styleWidth >= docClientWidth ) 
                        {
                            input.style.width = docClientWidth - absOffsetWidth;
                        }
                         else
                        {
                            input.style.width = input.scrollWidth+2;
                        }
                    }
                }
                </script>";
             if ( ! this.Page.IsStartupScriptRegistered(SCRIPT_KEY) )
            {
                 this.Page.RegisterStartupScript(SCRIPT_KEY, strScript);
            }
        }
    }
}
#endregion

本文转自博客园鸟食轩的博客,原文链接:http://www.cnblogs.com/birdshome/,如需转载请自行联系原博主。

目录
相关文章
Winform中Textbox、NumericUpDown等修改高度,禁止输入数字或内容的实现
Winform中的Textbox、NumericUpDown控件通常在单行的情况下,无法直接通过`Height`属性修改高度,但很多时候我们需要调整其高度,使其显示的更加合理,主要介绍三种方法...
2337 0
|
6月前
textarea文本框根据输入内容自动适应高度
textarea文本框根据输入内容自动适应高度
86 0
|
6月前
|
C++
[Qt5&控件] Label控件显示文本内容(字符串和整数)
[Qt5&控件] Label控件显示文本内容(字符串和整数)
132 0
[Qt5&控件] Label控件显示文本内容(字符串和整数)
|
前端开发 测试技术
Easyui datagrid 设置内容超过单元格宽度时自动换行显示
Easyui datagrid 设置内容超过单元格宽度时自动换行显示
422 0
|
存储 前端开发 C++
2.8 输入控件(三)
2.8 输入控件(三)
2.8 输入控件(三)
|
数据安全/隐私保护 C++
2.8 输入控件(一)
2.8 输入控件(一)
2.8 输入控件(一)
|
C#
WPF TextBox/TextBlock 文本超出显示时,文本靠右显示
原文:WPF TextBox/TextBlock 文本超出显示时,文本靠右显示 文本框显示 文本框正常显示: 文本框超出区域显示:    实现方案 判断文本框是否超出区域 请见《TextBlock IsTextTrimmed 判断文本是否超出》 设置文本布局显示 1.
1675 0
|
C#
【WPF】设置TextBox内容为空时的提示文字
原文:【WPF】设置TextBox内容为空时的提示文字 ...
4664 0