여기에있는 모든 대답은 a를 사용 TextBox
하거나 텍스트 선택을 수동으로 구현하려고 시도하여 성능이 저하되거나 기본 동작이 아닙니다 (캐럿이 깜박이고 TextBox
수동 구현에서 키보드가 지원되지 않음).
몇 시간 동안 WPF 소스 코드 를 파고 읽은 후 TextBlock
컨트롤 (또는 실제로 다른 컨트롤)에 대한 기본 WPF 텍스트 선택을 활성화하는 방법을 발견했습니다 . 텍스트 선택과 관련된 대부분의 기능은 System.Windows.Documents.TextEditor
시스템 클래스 에서 구현됩니다 .
컨트롤에서 텍스트를 선택하려면 두 가지 작업을 수행해야합니다.
TextEditor.RegisterCommandHandlers()
한 번만 호출 하여 클래스 이벤트 핸들러를 등록하십시오.
TextEditor
클래스의 각 인스턴스에 대한 인스턴스를 만들고 기본 인스턴스를 전달 System.Windows.Documents.ITextContainer
하십시오.
컨트롤의 Focusable
속성이로 설정되어 있어야 True
합니다.
이거 야! 쉽게 들리지만 불행히도 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
텍스트를 선택할 수 있도록 연결된 속성을 만드는 것 입니다. 이 경우 선택을 다시 비활성화하려면 TextEditor
이 코드와 동일한 리플렉션을 사용하여 a를 분리해야 합니다.
_editor.TextContainer.TextView = null;
_editor.OnDetach();
_editor = null;