2008-11-23 11 views
2

Je voudrais une zone de texte qui permet un certain texte à l'intérieur d'être « constante » et non modifiable tandis que le reste du texte est modifiable. Par exemple, je voudrais définir un modèle comme celui-ci:multiligne Modèle de contrôle de texte en C#

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

Afin que l'utilisateur pourrait entrer plus tard:

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

Mais pas:

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

Idéalement, ils wouldn 't même être en mesure de mettre leur curseur entre les <>, similaire à des modèles Microsoft Word.

Des idées? Le contrôle de zone de texte masqué semble être sur le bon chemin, mais n'est pas multiligne et ne vous permet pas d'entrer un nombre variable de caractères entre les accolades, par exemple.

Merci d'avance.

Répondre

3

Je ne sais pas de tous les composants prêts à l'emploi. Mais vous pouvez essayer cette méthode simple.

  1. Créer une zone de texte multi-ligne normale commande
  2. Créer un modèle basé sur les expressions régulières qui a (.*) ou ([a-z]*) ou tout ce que vous voulez où l'utilisateur d'ajouter du texte.
  3. Chaque fois que le texte est modifié, vérifiez s'il correspond toujours à la regex. Si c'est le cas, acceptez le chagne. Si ce n'est pas le cas, rejetez le changement.

Vous pouvez ensuite utiliser la même expression rationnelle pour extraire vos données de la zone de texte.

Vous pouvez même utiliser un RichTextBox et utiliser l'expression rationnelle pour effectuer le formatage.

Mise à jour Voici ce que je l'ai écrit. Il semble fonctionner:

[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); 
    } 
} 
+0

Une variante de votre réponse semble être le billet. Nous avons d'abord pensé à regex, mais pas à accepter ou à rejeter les changements. Merci! –

+0

Et code ?! Beau. –

1

Je suggère d'utiliser plusieurs contrôles au lieu d'un seul. Une seule zone de texte obligerait l'utilisateur à passer au champ suivant, alors que plusieurs contrôles permettraient à l'utilisateur de passer d'un champ à l'autre, ce qui est un comportement attendu. Si vous voulez faire regarder comme un contrôle (peut-être pour le faire ressembler à une étiquette d'adresse, ou quelque chose), vous pouvez utiliser les zones de texte sans frontières et mettre les étiquettes et zones de texte tout dans un panneau qui a une bordure et un fond SystemColors.Window . Pour un effet supplémentaire, il peut être intéressant de placer des lignes sous chaque zone de texte, ce qui se fait facilement avec une étiquette haute de 1 pixel avec une bordure BorderStyle.FixedSingle.