如何解决尝试创建行为类似于VS编辑器窗口的WPF窗口
我使用了CodeProject中的CodeBox项目,除了不能禁用自动换行外,它的效果非常好。在普通的TextBox中,只需将textwrapping属性设置为Nowrap即可达到目的,但对于CodeBox(它是从代码隐藏的TextBox继承的)中却没有。我尝试添加水平滚动条,但这无济于事。滚动条是可见的,并且它更改了拖动按钮的大小,以表明它看到展开的文本比查看区域宽,但是由于该文本已经被包裹了,因此拖动没有任何区别。
我已将问题跟踪到OnRender中的一行:
“ formattedText.MaxTextWidth = this.ViewportWidth; //滚动条的空间”
我对WPF还是很陌生,它对我来说仍然是很多神秘的事物,因此对于有更多经验的人来说,解决方案可能是显而易见的。
任何建议,我将不胜感激。这是C#背后的代码,很长,但已被精简为仅显示出正在发生的事情。其余的(已被删除)只是可以使文本着色更多的代码。
public partial class CodeBox : TextBox
{
bool m_bScrollingEventEnabled;
SolidColorBrush m_brRed = new SolidColorBrush (Colors.Red);
SolidColorBrush m_brorange = new SolidColorBrush (Colors.Orange);
SolidColorBrush m_brBlack = new SolidColorBrush (Colors.Black);
public CodeBox ()
{
this.TextChanged += new TextChangedEventHandler (txtTest_TextChanged);
this.Foreground = new SolidColorBrush (Colors.Transparent);
this.Background = new SolidColorBrush (Colors.Transparent);
this.textwrapping = System.Windows.textwrapping.Nowrap;
base.textwrapping = System.Windows.textwrapping.Nowrap;
InitializeComponent ();
}
public static DependencyProperty BaseForegroundProperty = DependencyProperty.Register ("BaseForeground",typeof (Brush),typeof (CodeBox),new FrameworkPropertyMetadata (new SolidColorBrush (Colors.Black),FrameworkPropertyMetadataOptions.AffectsRender));
public Brush BaseForeground
{
get { return (Brush)GetValue (BaseForegroundProperty); }
set { SetValue (BaseForegroundProperty,value); }
}
public static DependencyProperty BaseBackgroundProperty = DependencyProperty.Register ("BaseBackground",FrameworkPropertyMetadataOptions.AffectsRender));
public Brush BaseBackground
{
get { return (Brush)GetValue (BaseBackgroundProperty); }
set { SetValue (BaseBackgroundProperty,value); }
}
void txtTest_TextChanged (object sender,TextChangedEventArgs e)
{
this.InvalidateVisual ();
}
protected override void OnRender (System.Windows.Media.DrawingContext drawingContext)
{
//base.OnRender(drawingContext);
if (this.Text.Length > 0)
{
EnsureScrolling ();
FormattedText formattedText = new FormattedText (
this.Text,CultureInfo.GetCultureInfo ("en-us"),FlowDirection.LeftToRight,new Typeface (this.FontFamily.source),this.FontSize,BaseForeground); //Text that matches the textBox's
double leftMargin = 4.0 + this.BorderThickness.Left;
double topMargin = 2 + this.BorderThickness.Top;
***formattedText.MaxTextWidth = this.ViewportWidth; // space for scrollbar***
formattedText.MaxTextHeight = Math.Max (this.ActualHeight + this.VerticalOffset,0); //Adjust for scrolling
drawingContext.PushClip (new RectangleGeometry (new Rect (0,this.ActualWidth,this.ActualHeight)));//restrict text to textBox
int iStartVisibleLine = GetFirstVisibleLineIndex ();
int iEndVisibleLine = GetLastVisibleLineIndex ();
for (int iIdx = iStartVisibleLine; iIdx <= iEndVisibleLine - 1; ++iIdx)
{
// Text coloring
int iOffset = GetCharacterIndexFromLineIndex (iIdx);
int iOffsetNext = GetCharacterIndexFromLineIndex (iIdx + 1);
string strLine = Text.Substring (iOffset,iOffsetNext - iOffset);
}
drawingContext.DrawText (formattedText,new Point (leftMargin,topMargin - this.VerticalOffset));
}
}
private void EnsureScrolling ()
{
if (!m_bScrollingEventEnabled)
{
DependencyObject dp = VisualTreeHelper.GetChild (this,0);
ScrollViewer sv = VisualTreeHelper.GetChild (dp,0) as ScrollViewer;
sv.ScrollChanged += new ScrollChangedEventHandler (ScrollChanged);
m_bScrollingEventEnabled = true;
}
}
private void ScrollChanged (object sender,ScrollChangedEventArgs e)
{
this.InvalidateVisual ();
}
}
该项目的xaml:
<TextBox x:Class="CodeBoxControl.CodeBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:c="clr-namespace:CodeBoxControl">
<TextBox.Template>
<ControlTemplate targettype="c:CodeBox" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Border BorderThickness="{TemplateBinding Border.BorderThickness}" BorderBrush="{TemplateBinding Border.BorderBrush}"
Background="{TemplateBinding Panel.Background}" Name="Bd" SnapsToDevicePixels="True">
<ScrollViewer Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="UIElement.IsEnabled">
<Setter Property="Panel.Background" TargetName="Bd">
<Setter.Value>
<DynamicResource ResourceKey="{x:Static SystemColors.ControlBrushKey}" />
</Setter.Value>
</Setter>
<Setter Property="TextElement.Foreground">
<Setter.Value>
<DynamicResource ResourceKey="{x:Static SystemColors.GrayTextBrushKey}" />
</Setter.Value>
</Setter>
<Trigger.Value>
<s:Boolean>False</s:Boolean>
</Trigger.Value>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</TextBox.Template>
<c:CodeBox Name="disassemblyOutput"
FontFamily="Courier New"
FontSize="20"
VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Auto"
BaseForeground="Black"
Margin="4,4,4"
Background="#CEE9C9"
Foreground="magenta"
textwrapping="Nowrap"
AutoWordSelection="False"/>
private void OnLoadDASM (object sender,RoutedEventArgs e)
{
disassemblyOutput.FontSize = 12;
disassemblyOutput.Clear ();
disassemblyOutput.m_eWindowData = CodeBox.EWindowData.EDasm;
disassemblyOutput.Background = new SolidColorBrush (Colors.Transparent);//Color.Fromrgb (0xCE,0xE9,0xC9));
disassemblyOutput.Foreground = new SolidColorBrush (Colors.Transparent);
disassemblyOutput.BaseBackground = new SolidColorBrush (Color.Fromrgb (0xCE,0xC9));
disassemblyOutput.BaseForeground = new SolidColorBrush (Colors.Transparent);
disassemblyOutput.textwrapping = textwrapping.Nowrap;
disassemblyOutput.Text += "Loop_02_0A0F 0A0F: SIO F3 10 28 5475 Keyboard Set Error Indicator Restore Data Key " + Environment.NewLine;
disassemblyOutput.Text += " disable Interrupt " + Environment.NewLine;
disassemblyOutput.Text += " 0A12: SNS 70 12 FF,1 0x0B0C 5475 Keyboard 2 sense bytes " + Environment.NewLine;
}
这就是我想要的: https://i.stack.imgur.com/M4ts0.png 以及显示的内容: https://i.stack.imgur.com/gdBco.png
我还注意到,当文本换行并且使用垂直滚动条时,窗格顶部的文本消失了,向下滚动的次数越多,消失的越多: 1
解决方法
解决方法是将MaxTextWidth设置为行的宽度,而不是ViewportWidth属性:
iStartVisibleLine = GetFirstVisibleLineIndex ();
iEndVisibleLine = GetLastVisibleLineIndex ();
iOffset = GetCharacterIndexFromLineIndex (0);
iOffsetNext = GetCharacterIndexFromLineIndex (1);
strLine = Text.Substring (iOffset,iOffsetNext - iOffset);
geomFirstLine = formattedText.BuildHighlightGeometry (new Point (leftMargin,topMargin - this.VerticalOffset),iOffset,strLine.Length);
rcBounds = geomFirstLine.GetRenderBounds (null);
formattedText.MaxTextWidth = rcBounds.Width; // Space for scrollbar
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。