使用C1RichTextBox实现剪贴板'剪切'操作

时间:2013-11-08 09:24:07

标签: silverlight richtextbox copy-paste componentone

由于SilverRore的C1RichTextBox(5.0.20132.340)中的大图像存在问题,我想在自定义控件中实现复制/剪切/粘贴操作。 我正在使用事件C1RichTextBox.ClipboardCopyingC1RichTextBox.ClipboardPasting来执行此操作。这些是唯一的事件(没有ClipboardCutting事件),我没有看到任何可重写的方法来解决这个问题。

现在,当我在富文本框中执行CUT操作时,事件C1RichTextBox.ClipboardCopying也被触发,但我无法确定它是复制还是剪切。内部使用私人成员C1RichTextBox._isCutOperation

如何决定是否正在复制或剪切?

1 个答案:

答案 0 :(得分:1)

我也在ComponentOne支持论坛中提出了这个问题,这是他们提出的问题:

  

我建议您更倾听Ctrl + X的KeyDown事件并调用   C1RichTextBox.ClipBoardCut方法。这样你就可以了   处理C1RichTextBox上的cur操作。

这使我得出结论,您无法使用事件ClipboardCopying来实现自定义复制/剪切操作。

修改:请参阅this question如何实施自定义复制/剪切/粘贴)

经过几个小时的修补后,我找到了以下解决方案(以防万一其他人为此疯狂):

public class C1RichTextBoxExt : C1RichTextBox
{
    public C1RichTextBoxExt( )
    {
        ClipboardMode = ClipboardMode.RichText;

        // Workaround for Copy/Paste issue in C1RichTextBox (5.0.20132.340) -> large images are not copied.
        ClipboardCopying += new EventHandler<ClipboardEventArgs>(RichTextBox_ClipboardCopying);
        ClipboardPasting += new EventHandler<ClipboardEventArgs>(RichTextBox_ClipboardPasting);
    }

    void RichTextBox_ClipboardCopying(object sender, ClipboardEventArgs e)
    {
        // store info in static fields since Silverlight clipboard cannot store html and text at the same time.
        _clipboardHtml = Selection.Html;
        _clipboardText = Selection.Text;

        // Another Workaround: cannot determine if Copy or Cut is going on ...
        // -> call the ClipboardCopy() method and let the C1RichTextBox do the cut/copy. Calling this method will
        //    however trigger the ClipboardCopying event again, so we most remove this method as event handler 
        //    temporarily.
        ClipboardCopying -= RichTextBox_ClipboardCopying;
        ClipboardCopy();
        ClipboardCopying += RichTextBox_ClipboardCopying;

        e.Handled = true; // operation is done, nothing more to do.
    }

    void RichTextBox_ClipboardPasting(object sender, ClipboardEventArgs e)
    {
        string current = Clipboard.GetText();
        // texts will not match exactly since C1 uses a different approach to copy text to the clipboard than
        // just using Selection.Text...

        if (TextsEqual(current, _clipboardText))
        {
            // text is the same -> assumption that html is still valid. Paste _clipboardHtml
            using (new DocumentHistoryGroup(DocumentHistory)) // enables undo/redo
            {
                // code from C1 library to paste html correctly ///////////////////
                C1Document c1Document = HtmlFilter.ConvertToDocument(_clipboardHtml);

                C1TextPointer c1TextPointer = c1Document.ContentStart;
                C1TextRange selection = Selection;
                C1TextPointer c1TextPointer2 = selection.Delete(!Selection.IsEmpty, false);

                List<Type> list = Enumerable.ToList<Type>(Enumerable.Select<C1TextElement, Type>(c1TextPointer2.Element.GetParents(), (C1TextElement elem) => elem.GetType()));
                list.Add(c1TextPointer2.Element.GetType());
                while (c1TextPointer.Symbol is StartTag && (c1TextPointer.Symbol as Tag).Element is C1Block && !((c1TextPointer.Symbol as Tag).Element is C1TableRowGroup) && list.Contains((c1TextPointer.Symbol as Tag).Element.GetType()))
                {
                    c1TextPointer = c1TextPointer.GetPositionAtOffset(1);
                }
                C1TextPointer c1TextPointer3 = c1Document.ContentEnd;
                while (c1TextPointer3.PreviousSymbol is EndTag)
                {
                    c1TextPointer3 = c1TextPointer3.GetPositionAtOffset(-1);
                }
                c1Document.FragmentRange = new C1TextRange(c1TextPointer, c1TextPointer3);
                selection.Fragment = c1Document;
                Selection = new C1TextRange(selection.End);
                Focus();
                // end of C1 library code ////////////////////////
            }
            e.Handled = true; // paste is done
        }
        else
        {
            // text is different -> something newer got copied from another control or application
            // -> let C1RichTextBox paste
        }
    }

    private bool TextsEqual(string t1, string t2)
    {
        if (string.IsNullOrEmpty(t1) || string.IsNullOrEmpty(t2))
        {
            return false;
        }

        IEnumerable<char> chars1 = t1.Where(c => Char.IsLetterOrDigit(c));
        t1 = new string(chars1.ToArray());

        IEnumerable<char> chars2 = t2.Where(c => Char.IsLetterOrDigit(c));
        t2 = new string(chars2.ToArray());

        return t1 == t2;
    }

    private static string _clipboardText;
    private static string _clipboardHtml;
}