0 votes

Comment créer une zone de texte multiligne qui affiche une apostrophe avant chaque ligne

Je veux une zone de texte multiligne qui affiche des apostrophes avant et après chaque ligne. Ainsi, la zone de texte ressemblera à :

" Bonjour cela "
" est un test  "
" de chaîne amusant "

Ou par exemple :

// Ceci est
// un commentaire
// sur plusieurs lignes.

Modifier : Ces caractères spéciaux doivent être en lecture seule et si l'utilisateur copie du texte à partir de la zone de texte, ces caractères ne doivent pas être inclus.

2voto

Ray Burns Points 38537

C'est très facile en utilisant deux zones de texte superposées. L'arrière est une zone de texte normale avec un padding supplémentaire et du texte transparent. L'avant a vos caractères supplémentaires mais a ses bordures cachées et IsHitTestVisible=False et Focusable=False donc il n'interagit pas avec l'utilisateur. L'utilisateur interagit exclusivement avec la zone de texte arrière mais la zone de texte avant est celle qui affiche le texte. Une liaison avec un convertisseur de valeur fait en sorte que la zone de texte avant affiche exactement ce que la zone de texte arrière affiche, plus les caractères supplémentaires.

Voici à quoi cela ressemblerait :

ExtraCharacterConverter est une simple classe IValueConverter qui implémente la méthode Convert en prenant la chaîne donnée, en y ajoutant des guillemets ou des // ou tout ce que vous voulez, et en retournant le résultat.

Notez que j'ai codé en dur une marge à gauche et à droite de 10 unités sur la zone de texte arrière, ce qui suppose une largeur particulière pour les caractères ajoutés. Cela doit être exactement la largeur des caractères ajoutés pour que le texte s'aligne correctement. Vous voulez que cela soit correct, sinon votre curseur et la position de la sélection de texte seront incorrects. Notez également que la valeur correcte changera lorsque vous modifierez votre taille de police et votre choix de caractères supplémentaires.

Une alternative facile au codage en dur de la marge serait de la définir comme une multi- liaison sur FontSize, FontFamily, FontWeight, etc., puis d'utiliser un IMultiValueConverter pour calculer la marge appropriée en fonction de ces valeurs.

Remarque : cette solution est légèrement insatisfaisante en ce qui concerne le schéma de couleurs pour la sélection de texte. Cela peut être corrigé, mais cela nécessite une solution plus complexe : la zone de texte arrière est la même mais son texte n'est pas invisible. La zone de texte avant est remplacée par un RichTextBox (ou TextBlock) dont le contenu est calculé dynamiquement pour être le texte avec des caractères supplémentaires, mais le texte régulier est transparent. Parce que c'est un RichTextBox, les caractères supplémentaires peuvent être visibles alors que les autres sont transparents.

1voto

Jrud Points 475

Pouvez-vous simplement créer un champ de texte défini par l'utilisateur en utilisant l'héritage avec la propriété multiline définie sur true, et un code spécial sur l'événement de modification de texte pour vérifier le premier et le dernier index sur chaque ligne pour s'assurer qu'il y ait un apostrophe là ? ou s'il n'y a pas moyen d'itérer sur les lignes, pouvez-vous simplement surveiller le caractère avant et après chaque chr(11) ou chr(13) ?

Cela ne serait pas difficile avec winforms, je ne suis pas sûr de WPF cependant.

\~~~~~Edit 1: 25/11/2009 9:12 CT~~~~~~~~

Si vous souhaitez que l'utilisateur ne puisse pas éditer ou manipuler les guillemets, vous pourriez écrire un code spécifique dans le gestionnaire d'événements KeyPressed (ou remplacer la fonction OnKeyPressed si vous créez un contrôle hérité) pour les empêcher d'ajouter des caractères avant ou après un chr(11) ou chr(13), et le rajouter immédiatement s'ils tentent de le supprimer, et annuler les saisies invalides.

J'ai écrit un code similaire à ceci en VB .NET pour un champ de texte d'argent. Cela peut vous aider à comprendre de quoi je parle, et cela peut vous aider dans ce que vous faites :

Protected Overrides Sub OnMouseClick(ByVal e As System.Windows.Forms.MouseEventArgs)
    If Me.SelectionStart = 0 Then
        Me.SelectionStart = Me.Text.Length
    End If
End Sub

Protected Overrides Sub OnTextChanged(ByVal e As System.EventArgs)
    If Not Me.Text.IndexOf("$") = 0 Then
        Me.Text = "$" + Me.Text.Replace("$", "")
    End If
    If Me.SelectionStart = 0 Then
        Me.SelectionStart = Me.Text.Length
    End If
End Sub

Protected Overrides Sub OnKeyPress(ByVal e As System.Windows.Forms.KeyPressEventArgs)
    If NOT ((Char.IsDigit(e.KeyChar) Or (e.KeyChar = CChar(".") And Not Me.Text.Contains(".")) Or Char.IsControl(e.KeyChar)) And (Not Char.IsDigit(e.KeyChar) Or (Me.SelectionStart <= Me.Text.IndexOf(".") + 2 Or Me.Text.IndexOf(".") = -1))) Then
        e.Handled = True
    End If
End Sub

0voto

Grant Peters Points 3718

Je dirais que votre meilleure option est de mettre en œuvre votre propre zone de texte (héritée directement de la zone de texte de base, pour bénéficier gratuitement de toutes les fonctionnalités) et de remplacer le code de dessin en écrivant vous-même chaque ligne (en préfixant/suffixant les apostrophes à mesure que vous écrivez chaque ligne).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X