我想在Witty中显示文本,这是一个开源的Twitter客户端,可以选择 . 它目前使用自定义文本块显示 . 我需要使用TextBlock,因为我'm working with the textblock'内联显示和格式化@username和链接作为超链接 . 经常请求是能够复制粘贴文本 . 为了做到这一点,我需要使TextBlock可选 .
我试图通过使用只读TextBox来显示文本,使其看起来像文本块,但这在我的情况下不起作用,因为TextBox没有内联 . 换句话说,我不能单独设置或格式化TextBox中的文本,就像我可以使用TextBlock一样 .
有任何想法吗?
14 回答
这里的所有答案都只是使用
TextBox
或尝试手动实现文本选择,这会导致性能不佳或非本机行为(TextBox
中闪烁插入符号,手动实现中没有键盘支持等)经过几个小时的挖掘并阅读WPF source code,我发现了一种为
TextBlock
控件(或实际上任何其他控件)启用本机WPF文本选择的方法 . 文本选择的大多数功能都在System.Windows.Documents.TextEditor
系统类中实现 .要为控件启用文本选择,您需要做两件事:
调用
TextEditor.RegisterCommandHandlers()
一次以注册类事件处理程序为您的类的每个实例创建
TextEditor
的实例,并将System.Windows.Documents.ITextContainer
的基础实例传递给它's also a requirement that your control' s
Focusable
属性设置为True
.就是这个!听起来很简单,但不幸的是
TextEditor
类被标记为内部 . 所以我不得不在它周围写一个反射包装器:我还创建了一个
SelectableTextBlock
派生自TextBlock
,采取上述步骤:另一种选择是为
TextBlock
创建附加属性,以便根据需要启用文本选择 . 在这种情况下,要再次禁用选择,需要使用与此代码等效的反射来分离TextEditor
:我一直无法找到真正回答这个问题的任何例子 . 所有答案都使用了Textbox或RichTextbox . 我需要一个允许我使用TextBlock的解决方案,这就是我创建的解决方案 .
我相信正确的方法是扩展TextBlock类 . 这是我用来扩展TextBlock类的代码,允许我选择文本并将其复制到剪贴板 . “sdo”是我在WPF中使用的命名空间引用 .
WPF Using Extended Class:
Code Behind for Extended Class:
Example Window Code:
为TextBlock创建ControlTemplate并将TextBox放在readonly属性集中 . 或者只使用TextBox并使其只读,然后您可以更改TextBox.Style以使其看起来像TextBlock .
将此样式应用于TextBox,就是这样(灵感来自this article):
我不确定你是否可以选择TextBlock,但另一种选择是使用RichTextBox - 它就像你建议的TextBox,但支持你想要的格式 .
根据Windows Dev Center:
TextBlock没有模板 . 因此,为了实现这一点,我们需要使用一个TextBox,其样式被更改为表现为textBlock .
有一个替代解决方案可能适用于此_1358223中所包含的RichTextBox - 当用户将鼠标悬停在控件上时,它使用触发器来交换控件模板 - 应该有助于提高性能
虽然问题确实说'可选'但我认为有意的结果是将文本放到剪贴板中 . 通过添加上下文菜单和名为copy的菜单项可以轻松,优雅地实现这一点,该菜单项将Textblock Text属性值放入剪贴板 . 无论如何只是一个想法 .
我在我的开源控件库中实现了SelectableTextBlock . 你可以像这样使用它:
我带了一些小修改