Как разрешить TextBlock
выбор текста?
Я попытался заставить его работать, отображая текст, используя TextBox только для чтения, стилизованный под текстовый блок, но в моем случае это не будет работать, потому что TextBox не имеет встроенных строк. Другими словами, как сделать его выбираемым?
Ответы:
TextBox
Вместо этого используйте с этими настройками, чтобы сделать его только для чтения и выглядеть как элементTextBlock
управления.источник
Все ответы здесь - просто использование
TextBox
или попытка осуществить выделение текста вручную, что приводит к низкой производительности или нестандартному поведению (мигание кареткиTextBox
, отсутствие поддержки клавиатуры в ручных реализациях и т. Д.)После нескольких часов копания и чтения исходного кода WPF , я вместо этого обнаружил способ включения встроенного выделения текста WPF для
TextBlock
элементов управления (или вообще любых других элементов управления). Большая часть функциональности вокруг выделения текста реализована вSystem.Windows.Documents.TextEditor
системном классе.Чтобы включить выделение текста для вашего контроля, вам нужно сделать две вещи:
Вызовите
TextEditor.RegisterCommandHandlers()
один раз, чтобы зарегистрировать обработчики событий классаСоздание экземпляра
TextEditor
для каждого экземпляра вашего класса и передать основной экземпляр вашихSystem.Windows.Documents.ITextContainer
к немуТакже существует требование, чтобы
Focusable
свойство вашего элемента управления было установлено наTrue
.Это оно! Звучит просто, но, к сожалению,
TextEditor
класс помечен как внутренний. Поэтому мне пришлось написать обертку для отражения:Я также создал
SelectableTextBlock
производную от того,TextBlock
что предпринимает шаги, отмеченные выше:Другой вариант - создать прикрепленное свойство,
TextBlock
чтобы включить выбор текста по требованию. В этом случае, чтобы снова отключить выделение, нужно отсоединить aTextEditor
, используя эквивалент отражения этого кода:источник
TextBlock
встраиваетHyperlink
s, покаHyperlink
оно не является последним встроенным в него. Добавление завершающего пустогоRun
к содержимому исправляет любую проблему, лежащую в основе, которая приводит кExecutionEngineException
выбрасыванию.TextTrimming="CharacterEllipsis"
наTextBlock
и доступная ширина недостаточна, если вы перемещаете указатель мыши над ..., он падает с System.ArgumentException «Запрошенный расстояние находится вне содержания связанного документа.» в System.Windows.Documents.TextPointer.InitializeOffset (позиция TextPointer, расстояние Int32, направление LogicalDirection) :( Не знаю, есть ли обходной путь, кроме как оставить TextTrimming равным None.Я не смог найти ни одного примера, чтобы действительно ответить на вопрос. Все ответы использовали Textbox или RichTextbox. Мне нужно было решение, которое позволило бы мне использовать TextBlock, и это решение я создал.
Я считаю, что правильный способ сделать это - расширить класс TextBlock. Это код, который я использовал для расширения класса TextBlock, чтобы позволить мне выделять текст и копировать его в буфер обмена. «sdo» - это ссылка на пространство имен, которую я использовал в WPF.
WPF используя расширенный класс:
Код позади для расширенного класса:
Пример кода окна:
источник
Примените этот стиль к вашему TextBox и все (вдохновлено этой статьей ):
источник
Создайте ControlTemplate для TextBlock и поместите TextBox внутрь с установленным свойством только для чтения. Или просто используйте TextBox и сделайте его доступным только для чтения, затем вы можете изменить TextBox.Style, чтобы он выглядел как TextBlock.
источник
Я не уверен, что вы можете сделать TextBlock доступным для выбора, но другой вариант будет использовать RichTextBox - он похож на TextBox, как вы предложили, но поддерживает желаемое форматирование.
источник
По данным Windows Dev Center :
источник
Хотя вопрос говорит «Выбираемый», я полагаю, что преднамеренные результаты - получить текст в буфер обмена. Этого можно легко и элегантно достичь, добавив контекстное меню и пункт меню под названием copy, который помещает значение свойства Textblock Text в буфер обмена. В любом случае, просто идея.
источник
У TextBlock нет шаблона. Таким образом, чтобы добиться этого, нам нужно использовать TextBox, стиль которого изменен, чтобы вести себя как textBlock.
источник
Существует альтернативное решение, которое может быть адаптировано к RichTextBox, описанному в этом сообщении в блоге - оно использует триггер для замены шаблона элемента управления, когда использование наводится на элемент управления - должно помочь с производительностью
источник
источник
Добавим к ответу @ torvin и, как упомянул в комментариях @Dave Huang, если вы
TextTrimming="CharacterEllipsis"
включили приложение, происходит сбой при наведении курсора на многоточие.Я пробовал другие варианты, упомянутые в теме, об использовании TextBox, но на самом деле это тоже не решение, так как он не показывает «многоточие», а также, если текст слишком длинный, чтобы вместить контейнер, выбирающий содержимое текстовое поле «прокручивается» внутри, что не является поведением TextBlock.
Я думаю, что лучшее решение - ответ @ torvin, но у него неприятный сбой при наведении на многоточие.
Я знаю, что это не красиво, но внутренняя подписка / отмена подписки на необработанные исключения и обработка исключения были единственным способом, который я нашел для решения этой проблемы, пожалуйста, поделитесь, если у кого-то есть лучшее решение :)
источник
Я реализовал SelectableTextBlock в моей библиотеке элементов управления с открытым исходным кодом. Вы можете использовать это так:
источник
Я принес несколько небольших модификаций
источник
источник