Chcę, aby tekst wyświetlany w Witty , kliencie Twittera typu open source, był możliwy do wyboru. Obecnie jest wyświetlany przy użyciu niestandardowego bloku tekstu. Muszę użyć TextBlock, ponieważ pracuję z liniami tekstu bloku, aby wyświetlać i formatować @nazwa_użytkownika i linki jako hiperłącza. Częstym żądaniem jest możliwość skopiowania i wklejenia tekstu. W tym celu należy ustawić opcję TextBlock.
Próbowałem uruchomić go, wyświetlając tekst za pomocą TextBoxa tylko do odczytu, w stylu przypominającym blok tekstowy, ale to nie działa w moim przypadku, ponieważ TextBox nie ma wstawek. Innymi słowy, nie mogę stylizować ani formatować tekstu w TextBox indywidualnie, tak jak mogę to zrobić z TextBlock.
Jakieś pomysły?
Odpowiedzi:
źródło
Wszystkie odpowiedzi tutaj używają po prostu
TextBox
lub próbują zaimplementować zaznaczenie tekstu ręcznie, co prowadzi do niskiej wydajności lub nienatywnego zachowania (mruganie okiemTextBox
, brak obsługi klawiatury w implementacjach ręcznych itp.)Po wielu godzinach przekopywania się i czytaniu kodu źródłowego WPF , zamiast tego odkryłem sposób na włączenie natywnego zaznaczania tekstu WPF dla
TextBlock
formantów (lub naprawdę innych formantów). Większość funkcji związanych z zaznaczaniem tekstu jest zaimplementowana wSystem.Windows.Documents.TextEditor
klasie systemowej.Aby włączyć zaznaczanie tekstu dla swojej kontroli, musisz zrobić dwie rzeczy:
Zadzwoń
TextEditor.RegisterCommandHandlers()
raz, aby zarejestrować procedury obsługi zdarzeń klasowychTworzenie instancji
TextEditor
dla każdej instancji klasy i przekazać podstawową otworzonymSystem.Windows.Documents.ITextContainer
do niegoIstnieje również wymóg, aby
Focusable
właściwość kontroli była ustawiona naTrue
.To jest to! Brzmi łatwo, ale niestety
TextEditor
klasa jest oznaczona jako wewnętrzna. Musiałem więc napisać wokół niego opakowanie refleksyjne:Stworzyłem również
SelectableTextBlock
pochodną,TextBlock
która wykonuje czynności wymienione powyżej:Inną opcją byłoby utworzenie dołączonej właściwości
TextBlock
umożliwiającej zaznaczanie tekstu na żądanie. W takim przypadku, aby ponownie wyłączyć zaznaczenie, należy odłączyć aTextEditor
za pomocą równoważnika odbicia tego kodu:źródło
TextBlock
został osadzonyHyperlink
s, dopókiHyperlink
nie jest ostatnim inline w nim. Dodanie pustegoRun
końca do treści rozwiązuje problem leżący u podstaw, który powodujeExecutionEngineException
rzucenie.TextTrimming="CharacterEllipsis"
naTextBlock
i dostępna szerokość jest wystarczająca, jeśli przesunąć wskaźnik myszy nad ..., to wywala z System.ArgumentException „Żądana odległość jest poza treścią towarzyszącym dokumencie.” w System.Windows.Documents.TextPointer.InitializeOffset (pozycja TextPointer, odległość Int32, kierunek LogicalDirection) :( Nie wiem, czy istnieje inne obejście niż pozostawienie TextTrimming ustawionej na None.Nie znalazłem żadnego przykładu odpowiedzi na pytanie. Wszystkie odpowiedzi wykorzystały pole tekstowe lub RichTextbox. Potrzebowałem rozwiązania, które pozwoliło mi korzystać z TextBlock, i właśnie to stworzyłem.
Uważam, że poprawnym sposobem jest rozszerzenie klasy TextBlock. To jest kod, którego użyłem do rozszerzenia klasy TextBlock, aby umożliwić mi zaznaczenie tekstu i skopiowanie go do schowka. „sdo” to odniesienie do przestrzeni nazw, której użyłem w WPF.
WPF przy użyciu klasy rozszerzonej:
Kod za klasą rozszerzoną:
Przykładowy kod okna:
źródło
Zastosuj ten styl do TextBox i to wszystko (inspirowane tym artykułem ):
źródło
Utwórz ControlTemplate dla TextBlock i umieść TextBox wewnątrz z zestawem właściwości tylko do odczytu. Lub po prostu użyj TextBox i uczyń go tylko do odczytu, a następnie możesz zmienić TextBox.Style, aby wyglądał jak TextBlock.
źródło
Nie jestem pewien, czy możesz ustawić TextBlock do wyboru, ale inną opcją byłoby użycie RichTextBox - jest jak TextBox, jak sugerowałeś, ale obsługuje odpowiednie formatowanie.
źródło
Według Windows Dev Center :
źródło
Chociaż pytanie brzmi „do wyboru”, uważam, że zamierzonym rezultatem jest przeniesienie tekstu do schowka. Można to łatwo i elegancko osiągnąć poprzez dodanie menu kontekstowego i pozycji menu o nazwie kopiowanie, która umieszcza wartość właściwości Textblock Text w schowku. W każdym razie tylko pomysł.
źródło
TextBlock nie ma szablonu. Aby to osiągnąć, musimy użyć TextBox, którego styl został zmieniony, aby zachowywał się jak TextBlock.
źródło
Istnieje alternatywne rozwiązanie, które można dostosować do RichTextBox, zamieszczonego w tym poście na blogu - użyło wyzwalacza, aby zamienić szablon kontrolny, gdy najechanie kursorem na kontrolę - powinno pomóc w wydajności
źródło
źródło
Dodanie do odpowiedzi @ torvin i jak wspomniano w komentarzach @Dave Huang, jeśli
TextTrimming="CharacterEllipsis"
włączyłeś aplikację, ulega awarii po najechaniu kursorem na elipsę.Wypróbowałem inne opcje wymienione w wątku dotyczące korzystania z TextBox, ale tak naprawdę nie wydaje się to rozwiązaniem, ponieważ nie pokazuje „elipsy”, a także jeśli tekst jest zbyt długi, aby zmieścił się w pojemniku, wybierając zawartość pole tekstowe „przewija się” wewnętrznie, co nie jest zachowaniem TextBlock.
Myślę, że najlepszym rozwiązaniem jest odpowiedź @ torvina, ale ma paskudną awarię podczas najechania na elipsę.
Wiem, że to nie jest ładne, ale subskrybowanie / wypisywanie się wewnętrznie z nieobsługiwanymi wyjątkami i obsługa wyjątku była jedynym sposobem, w jaki znalazłem rozwiązanie tego problemu, proszę podziel się, jeśli ktoś ma lepsze rozwiązanie :)
źródło
Zaimplementowałem SelectableTextBlock w mojej bibliotece kontrolek opensource. Możesz użyć tego w następujący sposób:
źródło
źródło
Wprowadzam małe modyfikacje
źródło