在使用IE 10的Silverlight 5中使用C1RichTextBox时,我面临两个主要问题:
-
在剪贴板粘贴操作期间,如何检测内容是从Silverlight应用程序中的另一个
C1RichTextBox
还是从外部应用程序复制的?从外部应用程序,只应粘贴文本而不进行格式化 . -
从一个C1RichTextBox复制/粘贴大型内嵌图像不起作用 .
<img>
元素将图像内容存储在其数据URL中 . 如果图像变得太大(大约1MB),则复制到剪贴板时会删除src
属性 .
解决方案应该:
-
没有全局剪贴板或
C1RichTextBox
的编辑行为的副作用 . -
对
C1RichTextBox
实施的更改具有可靠性 . -
无需修改/解析/分析剪贴板中的HTML文档 .
1 回答
我花了一段时间来计算所有这些(更多......),我很高兴与任何必须处理这些问题的人分享 .
我正在使用派生类来解决问题
1.从外部应用程序粘贴纯文本
解决方案理论上很简单:在RichTextBox中的文本被复制/剪切到剪贴板后,获取HTML . 粘贴时,将剪贴板中的当前HTML与上次复制的内容进行比较 . 因为ComponentOne中的剪贴板是全局的,所以如果在另一个应用程序中完成复制/剪切,则内容会更改,因此HTML将不同 .
要记住上次复制的HTML,我们在
C1RichTextBoxExt
中使用静态成员:坏消息是:
C1RichTextBox.ClipboardCopy()
等方法不是虚拟的 . 好消息是:可以禁用调用这些方法的复制/剪切/粘贴的键盘快捷键,例如:在构造函数中:既然不再调用方法
C1RichTextBox.ClipboardCopy()
等,我们可以通过覆盖OnKeyDown
来连接我们自己的版本:为了不小心调用基类方法,我覆盖它们(见下文,使用
new
修饰符) .ClipboardCopy()
方法只调用基类,然后存储剪贴板HTML . 这里的一个小陷阱是使用Dispatcher.BeginInvoke()
,因为C1RichTextBox.ClipboardCopy()
将所选文本存储在Dispatcher.BeginInvoke()
调用内的剪贴板中 . 因此,只有在调度员有机会运行C1RichTextBox
提供的操作后,才能使用该内容 .ClipboardCut
方法非常相似:ClipboardPaste
方法现在可以检测是否粘贴外部数据 . 仅粘贴文本并非如此简单 . 我想出了用剪贴板的纯文本表示替换当前剪贴板内容的想法 . 粘贴完成后,应该恢复剪贴板,以便可以在其他应用程序中再次粘贴内容 . 这也必须在Dispatcher.BeginInvoke()
内完成,因为基类方法C1RichTextBox.ClipboardPaste()
也在延迟动作中执行粘贴操作 .2.复制/粘贴大型内嵌图像
这里的想法是类似的:复制时记住图像,在粘贴期间将它们放回原处 .
首先,我们需要存储文档中图像的位置:
(_imageCounter的使用将在后面解释......)
然后,在执行复制/剪切之前,我们搜索所有图像:
和类似的:
查找图像的方法是:
我不会详细介绍上述方法,如果分析
C1RichTextBox.Document
的结构,它们非常简单 .现在,我们如何恢复图像?我找到的最好的是使用
C1RichTextBox.HtmlFilter
的ConvertingHtmlNode
事件 . 每次将HTML节点转换为C1TextElement时都会触发此事件 . 我们在构造函数中订阅它:并像这样实现它:
因此,对于名称为"img"的每个HTML元素节点,我们检查是否缺少"src"属性 . 如果是这样,我们将添加下一个存储的图像并通过设置
e.Handled = true;
告诉事件源现在处理该事件(对于此HTML节点)_2777395_图像由"next"字段确定,该字段针对每个访问过的"img"元素递增 .调用
ClipboardPaste()
时必须重置_imageCounter
字段,因此我们执行以下操作:结论
如果你复制/粘贴(没有双关语......)所有代码块一起发布在上面,你应该得到一个没有副作用的解决方案(至少今天作者都不知道),对变化是强有力的几乎没有HTML处理 .