如何允许TextBlock的文本是可选的?

我试图让它通过显示文本使用只读文本框样式看起来像一个文本块,但这不会在我的情况下工作,因为一个文本框没有内联。换句话说,如何使它具有可选性?


当前回答

虽然这个问题确实说“可选择”,但我相信有意的结果是将文本放到剪贴板上。这可以通过添加一个名为复制的上下文菜单和菜单项来轻松而优雅地实现,该菜单项将Textblock Text属性值放在剪贴板中。只是一个想法而已。

其他回答

为torvin的代码添加了Selection & SelectionChanged事件

public class SelectableTextBlock : TextBlock
{

    static readonly Type TextEditorType
    = Type.GetType("System.Windows.Documents.TextEditor, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");

    static readonly PropertyInfo IsReadOnlyProp
        = TextEditorType.GetProperty("IsReadOnly", BindingFlags.Instance | BindingFlags.NonPublic);

    static readonly PropertyInfo TextViewProp
        = TextEditorType.GetProperty("TextView", BindingFlags.Instance | BindingFlags.NonPublic);

    static readonly MethodInfo RegisterMethod
        = TextEditorType.GetMethod("RegisterCommandHandlers",
        BindingFlags.Static | BindingFlags.NonPublic, null, new[] { typeof(Type), typeof(bool), typeof(bool), typeof(bool) }, null);

    static readonly Type TextContainerType
        = Type.GetType("System.Windows.Documents.ITextContainer, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");
    static readonly PropertyInfo TextContainerTextViewProp
        = TextContainerType.GetProperty("TextView");

    static readonly PropertyInfo TextContainerTextSelectionProp
        = TextContainerType.GetProperty("TextSelection");

    static readonly PropertyInfo TextContainerProp = typeof(TextBlock).GetProperty("TextContainer", BindingFlags.Instance | BindingFlags.NonPublic);

    static void RegisterCommandHandlers(Type controlType, bool acceptsRichContent, bool readOnly, bool registerEventListeners)
    {
        RegisterMethod.Invoke(null, new object[] { controlType, acceptsRichContent, readOnly, registerEventListeners });
    }

    static SelectableTextBlock()
    {
        FocusableProperty.OverrideMetadata(typeof(SelectableTextBlock), new FrameworkPropertyMetadata(true));
        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;
    object? textContainer;
    object? editor;
    public TextSelection TextSelection { get; private set; }

    public SelectableTextBlock()
    {
        textContainer = TextContainerProp.GetValue(this);

        editor = Activator.CreateInstance(TextEditorType, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.CreateInstance,
            null, new[] { textContainer, this, false }, null);


        IsReadOnlyProp.SetValue(editor, true);
        TextViewProp.SetValue(editor, TextContainerTextViewProp.GetValue(textContainer));

        TextSelection = (TextSelection)TextContainerTextSelectionProp.GetValue(textContainer);
        TextSelection.Changed += (s, e) => OnSelectionChanged?.Invoke(this, e);
    }

    public event EventHandler OnSelectionChanged;
}

有一个替代的解决方案,可能适用于这篇博客文章中提到的RichTextBox -它使用一个触发器来交换控件模板,当使用悬停在控件上时-应该有助于性能

创建控件模板的TextBlock,并把一个文本框内readonly属性设置。 或者只是使用文本框,使其只读,然后你可以改变文本框。样式,使它看起来像TextBlock。

根据Windows Dev Center:

TextBlock。IsTextSelectionEnabled财产 [针对Windows 10上的UWP应用程序更新。]Windows 8。X篇文章,见 档案] 获取或设置一个值,该值指示是否启用文本选择 在TextBlock中,通过用户操作或调用 selection-related API。

以下是对我有效的方法。我创建了一个类TextBlockEx,从TextBox派生,并设置为只读,文本包装在构造函数。

public class TextBlockEx : TextBox
{
    public TextBlockEx()
    {
        base.BorderThickness = new Thickness(0);
        IsReadOnly = true;
        TextWrapping = TextWrapping.Wrap;
        //Background = Brushes.Transparent; // Uncomment to get parent's background color
    }
}