<p>I'd like a textbox that allows for certain text within to be "constant" and uneditable while the rest of the text is editable.  For instance, I'd like to define a template like this:</p>

<pre><code>&lt;Name:&gt;[]
&lt;Address:&gt;[] &lt;City&gt;:[]
</code></pre>

<p>So that the user could later enter:</p>

<pre><code>&lt;Name:&gt;[Stefan]
&lt;Address:&gt;[Nowhere] &lt;City&gt;:[Alaska]
</code></pre>

<p>But not:</p>

<pre><code>&lt;I'm typing here lol:&gt;[Stefan]
&lt;Address:&gt;[Nowhere] &lt;State&gt;:[Alaska]
</code></pre>

<p>Ideally, they wouldn't even be able to put their cursor in between the &lt;>, similar to Microsoft Word templates.</p>

<p>Any ideas?  The masked textbox control seems to be along the right path, but isn't multiline and doesn't allow you to enter a variable number of characters in between the braces, for instance.</p>

<p>Thanks in advance.</p>

I don't know of any ready-made components. But you could try this simple method.
Create a normal multi-line text box control
Create a regex-based template that has
```
(.*)
```
or
```
([a-z]*)
```
or whatever wherever you want the user to add text.
Whenever the text is changed, checked if it still matches the regex. If it does, accept the chagne. If it doesn't, reject the change.
You can then use the same regex to extract your data from the text box.
You could even use a RichTextBox and use the regex to perform formatting.
Update
Here's what I wrote. It seems to work:
```
```
[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);
    }
}
```
```