Ich möchte den Text in Witty , einem Open-Source-Twitter-Client, auswählbar machen. Es wird derzeit mit einem benutzerdefinierten Textblock angezeigt. Ich muss einen TextBlock verwenden, da ich mit den Inlines des Textblocks arbeite, um den @Benutzernamen und die Links als Hyperlinks anzuzeigen und zu formatieren. Eine häufige Anforderung besteht darin, den Text kopieren und einfügen zu können. Dazu muss ich den TextBlock auswählbar machen.
Ich habe versucht, es zum Laufen zu bringen, indem ich den Text mit einer schreibgeschützten TextBox angezeigt habe, die so gestaltet ist, dass sie wie ein Textblock aussieht. In meinem Fall funktioniert dies jedoch nicht, da eine TextBox keine Inlines enthält. Mit anderen Worten, ich kann den Text in einer TextBox nicht wie bei einem TextBlock einzeln formatieren oder formatieren.
Irgendwelche Ideen?
Antworten:
quelle
Alle Antworten hier verwenden lediglich eine
TextBox
oder versuchen, die Textauswahl manuell zu implementieren, was zu einer schlechten Leistung oder einem nicht nativen Verhalten führt (blinkendes Caret in)TextBox
, keine Tastaturunterstützung bei manuellen Implementierungen usw.).Nachdem ich mich stundenlang umgesehen und den WPF-Quellcode gelesen hatte , entdeckte ich stattdessen eine Möglichkeit, die native WPF-Textauswahl für
TextBlock
Steuerelemente (oder wirklich alle anderen Steuerelemente) zu aktivieren . Die meisten Funktionen zur Textauswahl sind in der Systemklasse implementiertSystem.Windows.Documents.TextEditor
.Um die Textauswahl für Ihr Steuerelement zu aktivieren, müssen Sie zwei Dinge tun:
Rufen Sie
TextEditor.RegisterCommandHandlers()
einmal an, um Klassenereignishandler zu registrierenErstellen Sie eine Instanz von
TextEditor
für jede Instanz Ihrer Klasse und übergeben Sie die zugrunde liegende Instanz Ihrer KlasseSystem.Windows.Documents.ITextContainer
an dieseEs gibt auch eine Anforderung, auf die die
Focusable
Eigenschaft Ihres Steuerelements festgelegt istTrue
.Das ist es! Klingt einfach, aber leider
TextEditor
ist die Klasse als intern markiert. Also musste ich einen Reflection Wrapper darum schreiben:Ich habe auch eine
SelectableTextBlock
Ableitung erstelltTextBlock
, die die oben genannten Schritte ausführt:Eine andere Möglichkeit wäre, eine angehängte Eigenschaft zu erstellen
TextBlock
, um die Textauswahl bei Bedarf zu ermöglichen. In diesem Fall muss zum Löschen der Auswahl aTextEditor
unter Verwendung des Reflexionsäquivalents dieses Codes getrennt werden:quelle
TextBlock
eingebettet hat,Hyperlink
solange dasHyperlink
nicht die letzte Inline darin ist. Durch Hinzufügen eines nachgestellten LeerzeichensRun
zum Inhalt wird das zugrunde liegende Problem behoben , das zum Auslösen führtExecutionEngineException
.TextTrimming="CharacterEllipsis"
auf demTextBlock
und die zur Verfügung stehende Breite reicht nicht aus , wenn Sie den Mauszeiger über die bewegen ... es mit System.ArgumentException abstürzt „Gewünscht Abstand außerhalb des Inhalts des zugehörigen Dokuments.“ at System.Windows.Documents.TextPointer.InitializeOffset (TextPointer-Position, Int32-Abstand, LogicalDirection-Richtung) :( Ich weiß nicht, ob es eine andere Problemumgehung gibt, als TextTrimming auf None zu setzen.Ich konnte kein Beispiel finden, um die Frage wirklich zu beantworten. Alle Antworten verwendeten eine Textbox oder RichTextbox. Ich brauchte eine Lösung, mit der ich einen TextBlock verwenden konnte, und diese Lösung habe ich erstellt.
Ich glaube, der richtige Weg, dies zu tun, besteht darin, die TextBlock-Klasse zu erweitern. Dies ist der Code, mit dem ich die TextBlock-Klasse erweitert habe, damit ich den Text auswählen und in die Zwischenablage kopieren kann. "sdo" ist die Namespace-Referenz, die ich in der WPF verwendet habe.
WPF mit erweiterter Klasse:
Code Behind für Extended Class:
Beispielfenstercode:
quelle
Wenden Sie diesen Stil auf Ihre TextBox an und fertig (inspiriert von diesem Artikel ):
quelle
Erstellen Sie ControlTemplate für den TextBlock und fügen Sie eine TextBox mit schreibgeschütztem Eigenschaftssatz ein. Oder verwenden Sie einfach TextBox und machen Sie es schreibgeschützt. Dann können Sie die TextBox.Style so ändern, dass sie wie TextBlock aussieht.
quelle
Ich bin nicht sicher, ob Sie einen TextBlock auswählbar machen können, aber eine andere Option wäre die Verwendung einer RichTextBox - sie ähnelt einer von Ihnen vorgeschlagenen TextBox, unterstützt jedoch die gewünschte Formatierung.
quelle
Laut Windows Dev Center :
quelle
Während die Frage "Auswählbar" lautet, glaube ich, dass das beabsichtigte Ergebnis darin besteht, den Text in die Zwischenablage zu bringen. Dies kann einfach und elegant erreicht werden, indem ein Kontextmenü und ein Menüelement namens "Kopieren" hinzugefügt werden, mit denen der Eigenschaftswert "Textblock-Text" in die Zwischenablage verschoben wird. Nur eine Idee.
quelle
TextBlock hat keine Vorlage. Um dies zu erreichen, müssen wir eine TextBox verwenden, deren Stil geändert wird, um sich als TextBlock zu verhalten.
quelle
Es gibt eine alternative Lösung, die möglicherweise an die in diesem Blogbeitrag beschriebene RichTextBox angepasst werden kann - sie hat einen Auslöser verwendet, um die Steuerelementvorlage auszutauschen, wenn die Verwendung über dem Steuerelement schwebt -, um die Leistung zu verbessern
quelle
quelle
Das Hinzufügen zu @ torvins Antwort und wie @ Dave Huang in den Kommentaren erwähnt, wenn Sie
TextTrimming="CharacterEllipsis"
die Anwendung aktiviert haben, stürzt ab, wenn Sie mit der Maus über die Auslassungspunkte fahren.Ich habe andere im Thread erwähnte Optionen zur Verwendung einer TextBox ausprobiert, aber es scheint auch nicht die Lösung zu sein, da es nicht die Auslassungspunkte anzeigt und auch, wenn der Text zu lang ist, um in den Container zu passen, in dem der Inhalt ausgewählt wird Das Textfeld "scrollt" intern, was kein TextBlock-Verhalten ist.
Ich denke, die beste Lösung ist @ torvins Antwort, hat aber den bösen Absturz, wenn man über der Ellipse schwebt.
Ich weiß, dass es nicht schön ist, aber das interne Abonnieren / Abbestellen nicht behandelter Ausnahmen und das Behandeln der Ausnahme war die einzige Möglichkeit, dieses Problem zu lösen. Bitte teilen Sie mir mit, ob jemand eine bessere Lösung hat :)
quelle
Ich habe SelectableTextBlock in meiner OpenSource-Steuerelementbibliothek implementiert . Sie können es so verwenden:
quelle
quelle
Ich bringe einige kleine Modifikationen mit
quelle