WPF RichTextBox中的只读运行元素?
我可能完全在想象这一点,但我可以发誓有一种方法可以使RichTextBox中的单个Run(或paragraph)元素只读。我还可以发誓,几周前我自己也尝试过一种方法来解决这个问题,并且对结果感到满意——我隐约记得它看起来像这样:WPF RichTextBox中的只读运行元素?,wpf,xaml,richtextbox,.net-3.5,Wpf,Xaml,Richtextbox,.net 3.5,我可能完全在想象这一点,但我可以发誓有一种方法可以使RichTextBox中的单个Run(或paragraph)元素只读。我还可以发誓,几周前我自己也尝试过一种方法来解决这个问题,并且对结果感到满意——我隐约记得它看起来像这样: <RichTextBox x:Name="richTextBox" AcceptsTab="True" AcceptsReturn="True" FontFamily="Courier
<RichTextBox x:Name="richTextBox"
AcceptsTab="True"
AcceptsReturn="True"
FontFamily="Courier New"
FontSize="14">
<FlowDocument>
<Paragraph>
<Run IsReadOnly="True">I wish this was read-only!</Run>
</Paragraph>
</FlowDocument>
</RichTextBox>
我希望这是只读的!
现在,几周后,我尝试在RichTextBox中将Run元素设置为只读,结果发现这似乎是不可能的
似乎证实了这一点
我完全想象到了吗?或者有什么方法可以做我想做的吗?好吧,我想出了一个适合我的解决方案——但可能不适合所有想要这样做的人。它很凌乱,但它能起作用 我不会在几天内接受我自己的答案,以防万一其他人有更好的方法来实现这一点 我们开始吧,首先是XAML:
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1"
Height="500"
Width="600">
<DockPanel LastChildFill="True">
<RichTextBox x:Name="rtb"
FontFamily="Courier New"
FontSize="14"
PreviewKeyDown="rtb_PreviewKeyDown">
<FlowDocument>
<Paragraph>
<InlineUIContainer Unloaded="InlineUIContainer_Unloaded">
<TextBlock FontFamily="Courier New" FontSize="14">This line of text is not editable.</TextBlock>
</InlineUIContainer>
<Run Foreground="Blue">But this is editable.</Run>
</Paragraph>
</FlowDocument>
</RichTextBox>
</DockPanel>
</Window>
我的解决方案依赖于这样一个事实:当从UI中删除InlineUIContainer
时,调用unload()
方法。此时,我只需在当前插入符号位置重新插入已删除的InlineUIContainer
与任何黑客一样,它也有许多缺点。我发现的缺点如下:
- 我想要只读的文本需要包装在
中。这对这个解决方案有点限制InlineUIContainer
- 我必须捕获“回车”键并手动插入换行符,否则,
每次按下回车键时都会持续触发。不好玩,但对我的案子来说很管用InlineUIContainer.unload()
这不是一个很好的解决方案,但我认为它会对我有用。正如我所说,我现在还不打算把它作为我自己问题的答案——希望其他人有更好的方法来解决这个问题。这可以通过处理两个事件来实现:1)OnMouseDown 2)OnPreviewKeyDown
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows;
using System.Windows.Input;
namespace WpfApplication2
{
public class MultiPartTextBox : TextBox
{
private string _prefix;
private string _content;
public string Prefix
{
get { return _prefix; }
set { _prefix = value;
Text = _prefix;
}
}
public string Content
{
get { return _content; }
set {
_content = value;
Text = _prefix + _content;
}
}
public MultiPartTextBox() { _prefix = string.Empty; }
protected override void OnMouseDown(MouseButtonEventArgs e)
{
base.OnMouseDown(e);
this.SelectionStart = _prefix.Length;
this.SelectionLength = 0;
}
//tab In
protected override void OnGotFocus(RoutedEventArgs e)
{
this.SelectionStart = _prefix.Length;
this.SelectionLength = 0;
base.OnGotFocus(e);
}
protected override void OnPreviewKeyDown(KeyEventArgs e)
{
if (e.Key == Key.Back
|| e.Key == Key.Delete
|| e.Key==Key.Left)
{
if (CaretIndex <= _prefix.Length)
{
e.Handled = true;
return;
}
}
base.OnPreviewKeyDown(e);
}
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Windows.Controls;
使用System.Windows;
使用System.Windows.Input;
命名空间WpfApplication2
{
公共类MultiPartTextBox:TextBox
{
私有字符串前缀;
私有字符串\u内容;
公共字符串前缀
{
获取{return\u prefix;}
设置{u前缀=值;
Text=_前缀;
}
}
公共字符串内容
{
获取{return\u content;}
集合{
_内容=价值;
文本=_前缀+_内容;
}
}
public MultiPartTextBox(){u prefix=string.Empty;}
MouseDown上的受保护覆盖无效(MouseButtonEventArgs e)
{
base.OnMouseDown(e);
this.SelectionStart=\u prefix.Length;
this.SelectionLength=0;
}
//插页
受保护的覆盖无效OnGotFocus(路由目标e)
{
this.SelectionStart=\u prefix.Length;
this.SelectionLength=0;
基地,昂戈特福克斯(e);;
}
PreviewKeyDown(KeyEventArgs e)上受保护的覆盖无效
{
如果(e.Key==Key.Back
||e.Key==Key.Delete
||e.Key==Key.Left)
{
if(CaretIndex)非常有趣,如果您愿意,它将帮助我将“小部件”添加到文本编辑器中。我正在制作一个非常好的窗口,如Wiki编辑器。因此,对于添加图像、类别和关键字,我使用小对象装饰富文本对象。我希望编辑器更像visual studio编辑器。这样我可以添加“装饰”但是…这确实帮了我的忙!谢谢。很高兴它能帮上忙-尽管有警告-我隐约记得可以用退格键删除只读文本。我不确定这么久之后,但我会彻底测试它,以确保小部件保持只读。你忘了触摸手指了。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows;
using System.Windows.Input;
namespace WpfApplication2
{
public class MultiPartTextBox : TextBox
{
private string _prefix;
private string _content;
public string Prefix
{
get { return _prefix; }
set { _prefix = value;
Text = _prefix;
}
}
public string Content
{
get { return _content; }
set {
_content = value;
Text = _prefix + _content;
}
}
public MultiPartTextBox() { _prefix = string.Empty; }
protected override void OnMouseDown(MouseButtonEventArgs e)
{
base.OnMouseDown(e);
this.SelectionStart = _prefix.Length;
this.SelectionLength = 0;
}
//tab In
protected override void OnGotFocus(RoutedEventArgs e)
{
this.SelectionStart = _prefix.Length;
this.SelectionLength = 0;
base.OnGotFocus(e);
}
protected override void OnPreviewKeyDown(KeyEventArgs e)
{
if (e.Key == Key.Back
|| e.Key == Key.Delete
|| e.Key==Key.Left)
{
if (CaretIndex <= _prefix.Length)
{
e.Handled = true;
return;
}
}
base.OnPreviewKeyDown(e);
}
}
}
xmlns:uc="clr-namespace:WpfApplication2"
<uc:MultiPartTextBox Height="30" HorizontalAlignment="Left"
Margin="80,94,0,0" x:Name="multiPartTxt1" VerticalAlignment="Top"
Width="224" Prefix="NON-EDITABLE" CaretIndex="4" >
</uc:MultiPartTextBox>