C#中的多行模板文本控件

时间:2008-11-23 02:04:18

标签: c# controls

我想要一个文本框,允许其中的某些文本“不变”且不可编辑,而文本的其余部分是可编辑的。例如,我想定义一个这样的模板:

<Name:>[]
<Address:>[] <City>:[]

以便用户稍后可以输入:

<Name:>[Stefan]
<Address:>[Nowhere] <City>:[Alaska]

但不是:

<I'm typing here lol:>[Stefan]
<Address:>[Nowhere] <State>:[Alaska]

理想情况下,他们甚至无法将光标置于&lt;&gt;之间,类似于Microsoft Word模板。

有什么想法吗?屏蔽的文本框控件似乎沿着正确的路径,但不是多线,并且不允许您在大括号之间输入可变数量的字符。例如。

提前致谢。

2 个答案:

答案 0 :(得分:3)

我不知道任何现成的组件。但你可以试试这个简单的方法。

  1. 创建普通的多行文本框控件
  2. 创建一个基于正则表达式的模板,该模板具有(.*)([a-z]*)或其他任何您希望用户添加文本的模板。
  3. 每当更改文本时,检查它是否仍然与正则表达式匹配。如果确实如此,请接受chagne。如果没有,请拒绝更改。
  4. 然后,您可以使用相同的正则表达式从文本框中提取数据。

    您甚至可以使用RichTextBox并使用正则表达式执行格式化。

    更新以下是我写的内容。它似乎有效:

    [DefaultProperty("Regex")]
    public partial class MaskedEdit : UserControl
    {
        private Regex regex = new Regex("");
        private bool myChange = false;
    
        private string goodText;
        private Font dataFont;
    
        public MaskedEdit()
        {
            myChange = true;
            InitializeComponent();
            myChange = false;
            dataFont = new Font(Font, FontStyle.Bold);
            goodText = Text;
        }
    
        [Editor("System.ComponentModel.Design.MultilineStringEditor, System.Design", typeof(UITypeEditor)), Localizable(true)]
        [DefaultValue("")]
        public String Regex
        {
            get { return regex.ToString(); }
            set
            {
                if (value != null)
                {
                    regex = new Regex(value);
                }
            }
        }
    
        [EditorBrowsable(EditorBrowsableState.Always)]
        [Browsable(true)] 
        [Editor("System.ComponentModel.Design.MultilineStringEditor, System.Design", typeof(UITypeEditor)), Localizable(true)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public override string Text
        {
            get { return rtf.Text; }
            set {
                int selSt = rtf.SelectionStart;
                int selLen = rtf.SelectionLength;
    
                rtf.Text = value;
    
                rtf.SelectionStart = selSt;
                rtf.SelectionLength = selLen;
            }
        }
    
        private void rtf_TextChanged(object sender, EventArgs e)
        {
            if (myChange) return;
            Match m = regex.Match(Text);
            if (m.Success)
            {
                goodText = Text;
                Colorize(m);
            }
            else
            {
                myChange = true;
                Text = goodText;
                myChange = false;
                m = regex.Match(Text);
                if (m.Success)
                {
                    Colorize(m);
                }
            }
        }
    
        public IEnumerable<string> Data
        {
            get
            {
                Match m = regex.Match(Text);
                bool first = true;
                foreach (Group g in m.Groups)
                {
                    if (first) { first = false; continue; }
                    yield return Text.Substring(g.Index, g.Length);
                }
            }
        }
    
        private void Colorize(Match m)
        {
            int selSt = rtf.SelectionStart;
            int selLen = rtf.SelectionLength;
    
            rtf.SelectionStart = 0;
            rtf.SelectionLength = rtf.TextLength;
            rtf.SelectionFont = Font;
            bool first = true;
            foreach (Group g in m.Groups)
            {
                if (first) { first = false; continue; }
                rtf.SelectionStart = g.Index;
                rtf.SelectionLength = g.Length;
                rtf.SelectionFont = dataFont;
            }
    
            rtf.SelectionStart = selSt;
            rtf.SelectionLength = selLen;
        }
    
        private void MaskedEdit_FontChanged(object sender, EventArgs e)
        {
            dataFont = new Font(Font, FontStyle.Bold);
        }
    }
    

答案 1 :(得分:1)

我建议使用多个控件而不是一个。单个文本框将要求用户将光标移动到下一个字段,而多个控件将允许用户在字段之间进行选项卡,这是预期的行为。如果你想让它像一个控件一样看起来(也许是为了使它看起来像地址标签或其他东西),你可以使用无边框文本框并将标签和文本框全部放在一个有一个控件的面​​板中。边框和SystemColors.Window背景。为了获得额外的效果,可以在每个文本框下方放置线条,这可以通过带有BorderStyle.FixedSingle边框的1像素高标签轻松完成。