คำตอบทั้งหมดที่นี่เป็นเพียงการใช้TextBoxหรือพยายามที่จะใช้การเลือกข้อความด้วยตนเองซึ่งนำไปสู่ประสิทธิภาพที่ต่ำหรือพฤติกรรมที่ไม่ใช่เจ้าของภาษา (กระพริบ caret ในTextBoxไม่มีการสนับสนุนแป้นพิมพ์ในการใช้งานด้วยตนเอง ฯลฯ )
หลังจากขุดไปหลายชั่วโมงและอ่านซอร์สโค้ด WPFฉันได้ค้นพบวิธีการเปิดใช้งานการเลือกข้อความดั้งเดิมของ WPF สำหรับTextBlockการควบคุม (หรือการควบคุมอื่น ๆ จริงๆ) ฟังก์ชันการทำงานส่วนใหญ่เกี่ยวกับการเลือกข้อความถูกนำไปใช้ในSystem.Windows.Documents.TextEditorคลาสระบบ
ในการเปิดใช้งานการเลือกข้อความสำหรับการควบคุมของคุณคุณต้องทำสองสิ่ง:
โทรTextEditor.RegisterCommandHandlers()หนึ่งครั้งเพื่อลงทะเบียนตัวจัดการเหตุการณ์ของคลาส
 
สร้างอินสแตนซ์TextEditorสำหรับแต่ละอินสแตนซ์ของคลาสของคุณและส่งอินสแตนซ์พื้นฐานของคุณSystem.Windows.Documents.ITextContainerไปยังคลาสนั้น
 
นอกจากนี้ยังมีความต้องการว่าการควบคุมของคุณตั้งค่าคุณสมบัติFocusableTrue
นี่ไง! ฟังดูง่าย แต่น่าเสียดายที่TextEditorคลาสนั้นถูกทำเครื่องหมายเป็นภายใน ดังนั้นฉันจึงต้องเขียนเสื้อคลุมสะท้อนรอบ:
class TextEditorWrapper
{
    private static readonly Type TextEditorType = Type.GetType("System.Windows.Documents.TextEditor, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");
    private static readonly PropertyInfo IsReadOnlyProp = TextEditorType.GetProperty("IsReadOnly", BindingFlags.Instance | BindingFlags.NonPublic);
    private static readonly PropertyInfo TextViewProp = TextEditorType.GetProperty("TextView", BindingFlags.Instance | BindingFlags.NonPublic);
    private static readonly MethodInfo RegisterMethod = TextEditorType.GetMethod("RegisterCommandHandlers", 
        BindingFlags.Static | BindingFlags.NonPublic, null, new[] { typeof(Type), typeof(bool), typeof(bool), typeof(bool) }, null);
    private static readonly Type TextContainerType = Type.GetType("System.Windows.Documents.ITextContainer, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");
    private static readonly PropertyInfo TextContainerTextViewProp = TextContainerType.GetProperty("TextView");
    private static readonly PropertyInfo TextContainerProp = typeof(TextBlock).GetProperty("TextContainer", BindingFlags.Instance | BindingFlags.NonPublic);
    public static void RegisterCommandHandlers(Type controlType, bool acceptsRichContent, bool readOnly, bool registerEventListeners)
    {
        RegisterMethod.Invoke(null, new object[] { controlType, acceptsRichContent, readOnly, registerEventListeners });
    }
    public static TextEditorWrapper CreateFor(TextBlock tb)
    {
        var textContainer = TextContainerProp.GetValue(tb);
        var editor = new TextEditorWrapper(textContainer, tb, false);
        IsReadOnlyProp.SetValue(editor._editor, true);
        TextViewProp.SetValue(editor._editor, TextContainerTextViewProp.GetValue(textContainer));
        return editor;
    }
    private readonly object _editor;
    public TextEditorWrapper(object textContainer, FrameworkElement uiScope, bool isUndoEnabled)
    {
        _editor = Activator.CreateInstance(TextEditorType, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.CreateInstance, 
            null, new[] { textContainer, uiScope, isUndoEnabled }, null);
    }
}
ฉันยังสร้างสิ่งที่SelectableTextBlockได้มาจากTextBlockขั้นตอนที่ระบุไว้ข้างต้น:
public class SelectableTextBlock : TextBlock
{
    static SelectableTextBlock()
    {
        FocusableProperty.OverrideMetadata(typeof(SelectableTextBlock), new FrameworkPropertyMetadata(true));
        TextEditorWrapper.RegisterCommandHandlers(typeof(SelectableTextBlock), true, true, true);
        // remove the focus rectangle around the control
        FocusVisualStyleProperty.OverrideMetadata(typeof(SelectableTextBlock), new FrameworkPropertyMetadata((object)null));
    }
    private readonly TextEditorWrapper _editor;
    public SelectableTextBlock()
    {
        _editor = TextEditorWrapper.CreateFor(this);
    }
}
อีกตัวเลือกหนึ่งคือสร้างคุณสมบัติที่แนบมาTextBlockเพื่อเปิดใช้งานการเลือกข้อความตามต้องการ ในกรณีนี้หากต้องการปิดการใช้งานการเลือกอีกครั้งเราต้องถอด a TextEditorโดยใช้การสะท้อนที่เทียบเท่ากับรหัสนี้:
_editor.TextContainer.TextView = null;
_editor.OnDetach();
_editor = null;