1

由于 C1RichTextBox for Silverlight (5.0.20132.340) 中的大图像问题,我想在我的自定义控件中实现复制/剪切/粘贴操作。我正在使用这些事件C1RichTextBox.ClipboardCopyingC1RichTextBox.ClipboardPasting做到这一点。这些是唯一的事件(没有 ClipboardCutting 事件),我没有看到任何可覆盖的方法来以不同的方式解决这个问题。

现在,当我在富文本框中执行 CUT 操作时,C1RichTextBox.ClipboardCopying也会触发该事件,但我无法确定它是 Copy 还是 Cut。有一个C1RichTextBox._isCutOperation内部使用的私有成员。

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

4

1 回答 1

1

我还在 ComponentOne 支持论坛中提出了这个问题,他们提出了以下问题:

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

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

编辑:见这个问题如何实现自定义复制/剪切/粘贴)

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

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;
}
于 2013-11-15T10:21:38.127 回答