如何允许TextBlock的文本是可选的?
我试图让它通过显示文本使用只读文本框样式看起来像一个文本块,但这不会在我的情况下工作,因为一个文本框没有内联。换句话说,如何使它具有可选性?
如何允许TextBlock的文本是可选的?
我试图让它通过显示文本使用只读文本框样式看起来像一个文本块,但这不会在我的情况下工作,因为一个文本框没有内联。换句话说,如何使它具有可选性?
当前回答
创建控件模板的TextBlock,并把一个文本框内readonly属性设置。 或者只是使用文本框,使其只读,然后你可以改变文本框。样式,使它看起来像TextBlock。
其他回答
使用带有这些设置的TextBox来使其只读,看起来像一个TextBlock控件。
<TextBox Background="Transparent"
BorderThickness="0"
Text="{Binding Text, Mode=OneWay}"
IsReadOnly="True"
TextWrapping="Wrap" />
TextBlock没有模板。因此,为了实现这一点,我们需要使用一个文本框,其风格被改变为一个文本块的行为。
<Style x:Key="TextBlockUsingTextBoxStyle" BasedOn="{x:Null}" TargetType="{x:Type TextBox}">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="{StaticResource TextBoxBorder}"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Padding" Value="1"/>
<Setter Property="AllowDrop" Value="true"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/>
<Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<TextBox BorderThickness="{TemplateBinding BorderThickness}" IsReadOnly="True" Text="{TemplateBinding Text}" Background="{x:Null}" BorderBrush="{x:Null}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
所有的答案在这里只是使用一个文本框或试图实现文本选择手动,这导致性能差或非本机行为(闪烁插入文本框,手动实现不支持键盘等)。
经过几个小时的挖掘和阅读WPF源代码,我反而发现了一种启用本地WPF文本选择TextBlock控件(或真正的任何其他控件)的方法。大多数关于文本选择的功能是在system . windows . documents . texteditor系统类中实现的。
要启用控件的文本选择,您需要做两件事:
调用一次texteitor . 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);
}
}
我还创建了一个从TextBlock派生的SelectableTextBlock,采取上述步骤:
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:
_editor.TextContainer.TextView = null;
_editor.OnDetach();
_editor = null;
创建控件模板的TextBlock,并把一个文本框内readonly属性设置。 或者只是使用文本框,使其只读,然后你可以改变文本框。样式,使它看起来像TextBlock。
public MainPage()
{
this.InitializeComponent();
...
...
...
//Make Start result text copiable
TextBlockStatusStart.IsTextSelectionEnabled = true;
}