RichTextBox放置在ViewBox中并放大到10 - 1000%的各个级别。在百分比低于100%的情况下,脱字符随机光标位置消失。ViewBox使RichTextBox失去它的插入
我明白,当视觉缩小(压缩)时,它会失去像素。有什么办法可以停止放松我的光标吗?
<Viewbox>
<RichTextBox Name="richTextBox1" Width="400" Height="400" />
</Viewbox>
RichTextBox放置在ViewBox中并放大到10 - 1000%的各个级别。在百分比低于100%的情况下,脱字符随机光标位置消失。ViewBox使RichTextBox失去它的插入
我明白,当视觉缩小(压缩)时,它会失去像素。有什么办法可以停止放松我的光标吗?
<Viewbox>
<RichTextBox Name="richTextBox1" Width="400" Height="400" />
</Viewbox>
最后编辑:
嘿,只是想说,你甚至可以在没有反思的情况下做到这一点!这不是优化的代码,我会为你自己留下。而且这仍然依赖于内部的东西。所以在这里谈到:
代码隐藏:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
rtb.LayoutUpdated += (sender, args) =>
{
var child = VisualTreeHelper.GetChild(vb, 0) as ContainerVisual;
var scale = child.Transform as ScaleTransform;
rtb.ScaleX = scale.ScaleX;
};
}
}
public class RTBwithVisibleCaret:RichTextBox
{
private UIElement _flowDocumentView;
private AdornerLayer _adornerLayer;
private UIElement _caretSubElement;
private ScaleTransform _scaleTransform;
public RTBwithVisibleCaret()
{
LayoutUpdated += (sender, args) =>
{
if (!IsKeyboardFocused) return;
if(_adornerLayer == null)
_adornerLayer = AdornerLayer.GetAdornerLayer(_flowDocumentView);
if (_adornerLayer == null || _flowDocumentView == null) return;
if(_scaleTransform != null && _caretSubElement!= null)
{
_scaleTransform.ScaleX = 1/ScaleX;
_adornerLayer.Update(_flowDocumentView);
}
else
{
var adorners = _adornerLayer.GetAdorners(_flowDocumentView);
if(adorners == null || adorners.Length<1) return;
var caret = adorners[0];
_caretSubElement = (UIElement) VisualTreeHelper.GetChild(caret, 0);
if(!(_caretSubElement.RenderTransform is ScaleTransform))
{
_scaleTransform = new ScaleTransform(1/ScaleX, 1);
_caretSubElement.RenderTransform = _scaleTransform;
}
}
};
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
var cthost = GetTemplateChild("PART_ContentHost") as FrameworkElement;
_flowDocumentView = cthost is ScrollViewer ? (UIElement)((ScrollViewer)cthost).Content : ((Decorator)cthost).Child;
}
public double ScaleX
{
get { return (double)GetValue(ScaleXProperty); }
set { SetValue(ScaleXProperty, value); }
}
public static readonly DependencyProperty ScaleXProperty =
DependencyProperty.Register("ScaleX", typeof(double), typeof(RTBwithVisibleCaret), new UIPropertyMetadata(1.0));
}
与此XAML工作:
<Window x:Class="RTBinViewBoxTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:RTBinViewBoxTest="clr-namespace:RTBinViewBoxTest" Title="MainWindow" Height="350" Width="525">
<Viewbox Height="100" x:Name="vb">
<RTBinViewBoxTest:RTBwithVisibleCaret Width="70" x:Name="rtb">
<FlowDocument>
<Paragraph>
<Run>long long long long long long long long long long long long long long long long long long long long long long long long text</Run>
</Paragraph>
</FlowDocument>
</RTBinViewBoxTest:RTBwithVisibleCaret>
</Viewbox>
</Window>
是的,这让我想到,当我看到,所有这些都是通过视觉树访问!而不是从RichTextBox继承(需要获取TemplateChild),您还可以遍历VisualTree以访问该FlowDocumentView!
原帖:
好吧,让我们来看看你的选择是:
在我上面的评论中指出:要完成这个对子级是有RichTextBox的内容变焦的最简单的方法,而不是RichTextBox在ViewBox中。你还没有回答(如果这是一个选项)。
现在一切将变得复杂,并或多或少存在问题:
可以使用Moq或类似的东西(认为痣左右...),以取代SystemParameters.CaretWidth,吸气,以适应ScaleTransform视框发挥。这有几个问题!第一:这些库是专门用于测试场景和不推荐用于生产使用。其次:您必须在RichTextBox实例化插入符之前设置该值。这很难,因为您事先并不知道ViewBox如何缩放RichTextBox。所以,这不是一个好的选择!
第二个(坏)选项将使用反射来到这个漂亮的小类System.Windows.Documents.CaretElement
。您可以通过RichTextBox.TextEditor.Selection.CaretElement
(您必须使用Reflection,因为这些属性和类大部分为internal sealed
)。因为这是一个装饰者,所以你可能会附加一个ScaleTransform来反转Scaling。我不得不说:这是既没有测试也没有推荐!
你的选择在这里是有限的,如果我是你,我会去我的第一个猜测!
编辑:
如果你真的想坐下即第二(坏的)途径,如果您应用ScaleTransform来,你可能有更多的运气装饰器一个孩子,你可以通过对私营领域_caretElement
得到键入CaretSubElement
。如果我正确读取该代码,那么该子元素就是您的实际Caret Visual。主要元素似乎用于绘制选择几何体。如果你真的想这样做,那么在那里应用ScaleTransform。
编辑:
完整的榜样:
XAML:
<Window x:Class="RTBinViewBoxTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Viewbox Height="100" x:Name="vb">
<RichTextBox Width="70" Name="rtb">
<FlowDocument>
<Paragraph>
<Run>long long long long long long long long long long long long long long long long long long long long long long long long text</Run>
</Paragraph>
</FlowDocument>
</RichTextBox>
</Viewbox>
</Window>
代码隐藏:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
rtb.GotFocus +=RtbOnGotFocus;
}
private void RtbOnGotFocus(object s, RoutedEventArgs routedEventArgs)
{
rtb.LayoutUpdated += (sender, args) =>
{
var child = VisualTreeHelper.GetChild(vb, 0) as ContainerVisual;
var scale = child.Transform as ScaleTransform;
rtb.Selection.GetType().GetMethod("System.Windows.Documents.ITextSelection.UpdateCaretAndHighlight", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(
rtb.Selection, null);
var caretElement=rtb.Selection.GetType().GetProperty("CaretElement", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(rtb.Selection, null);
if (caretElement == null)
return;
var caretSubElement = caretElement.GetType().GetField("_caretElement", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(caretElement) as UIElement;
if (caretSubElement == null) return;
var scaleTransform = new ScaleTransform(1/scale.ScaleX, 1);
caretSubElement.RenderTransform = scaleTransform;
};
}
}
这对我的作品。一切都在说。
缩放内容,而不是将RTB放入ViewBox中 - 工作太多! – Trainee4Life 2011-03-20 07:57:59
我看了第二个选项。这个解决方案的问题在于,装饰器的大小与实际大小相同(并且不等于实际的大小),因此ScaleTransform也会改变插入符号的位置。 – Trainee4Life 2011-03-20 08:03:03
@ Trainee4Life请看我的编辑。我仍然认为缩放内容会是更好的方法。 – 2011-03-20 09:44:38
AFAIK你不能真正解决这个问题。 ViewBox在封面下使用ScaleTransform,ScaleTransform在缩小时隐藏某些行,因为它无法显示所有内容。该ScaleTransform没有使用非常先进的算法,做规模,(这只是它尽可能以最快的方式),我不认为你可以改变的..
是否可以将RichTextBox的内容缩放到各个级别?像增加和减少与变量成比例的字体大小和页面宽度? – 2011-03-05 21:10:10
也许是对你的目标是什么的解释,以防有人可以想出一种不同的方法来处理它,而不是使用'ViewBox' +'RichTextBox'? – 2011-03-16 13:42:36
您定位的是什么版本的.NET/WPF? .NET/WPF 4? – CodeNaked 2011-03-17 16:18:42