Многострочный шаблон управления текстом в C # - PullRequest
2 голосов
/ 23 ноября 2008

Мне бы хотелось, чтобы текстовое поле позволяло определенному тексту быть «постоянным» и не редактируемым, а остальная часть текста редактируемой. Например, я хотел бы определить шаблон следующим образом:

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

Чтобы пользователь мог потом ввести:

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

Но не:

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

В идеале, они даже не смогли бы поместить курсор между <>, подобно шаблонам Microsoft Word.

Есть идеи? Элемент управления маскированным текстовым полем, кажется, идет по правильному пути, но не является многострочным и не позволяет вводить, например, переменное число символов между скобками.

Заранее спасибо.

Ответы [ 2 ]

3 голосов
/ 23 ноября 2008

Я не знаю ни одного готового компонента. Но вы можете попробовать этот простой метод.

  1. Создание обычного многострочного текстового поля управления
  2. Создайте шаблон на основе регулярных выражений, который имеет (.*) или ([a-z]*) или что угодно, где бы вы ни хотели, чтобы пользователь добавил текст.
  3. Всякий раз, когда текст изменяется, проверяется, соответствует ли он регулярному выражению. Если это так, примите эту тему. Если это не так, отклоните изменение.

Затем вы можете использовать то же регулярное выражение для извлечения ваших данных из текстового поля.

Вы можете даже использовать 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 голос
/ 23 ноября 2008

Я бы предложил использовать несколько элементов управления вместо одного. Одно текстовое поле потребует от пользователя навести курсор на следующее поле, тогда как несколько элементов управления позволят пользователю переключаться между полями, что является ожидаемым поведением. Если вы хотите, чтобы выглядел как один элемент управления (возможно, чтобы он выглядел как метка адреса или что-то в этом роде), вы можете использовать текстовые поля без полей и размещать метки и текстовые поля внутри панели с рамкой и SystemColors.Window фон. Для дополнительного эффекта было бы неплохо поместить строки под каждым текстовым полем, что легко сделать с помощью 1-пиксельной метки с границей BorderStyle.FixedSingle.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...