如何获取TextBox的内容宽度(VerticalScrollBar的宽度除外?

问题描述 投票:0回答:1

我创建了派生TextBox的HighlightTextBox。代码如下所示。

<Style TargetType="{x:Type host:HighlightTextBox}">
    <Setter Property="AcceptsReturn" Value="True" />
    <Setter Property="HorizontalScrollBarVisibility" Value="Auto" />
    <Setter Property="VerticalScrollBarVisibility" Value="Auto" />
    <Setter Property="TextWrapping" Value="NoWrap"/>
    <Setter Property="Foreground" Value="#00000000"/>
    <Setter Property="FontSize" Value="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=FontSize, Mode=TwoWay}"/>

    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate x:Name="textArea" TargetType="{x:Type host:HighlightTextBox}">
                <Border BorderThickness="{Binding BorderTickness}"
                            BorderBrush="{Binding BorderBrush}"
                            Background="{Binding BackGround}">

                    <Grid Margin="{TemplateBinding Padding}" x:Name="PART_Grid">
                        <host:TextCanvas x:Name="PART_RenderCanvas" ClipToBounds="True"
                                                    TextOptions.TextRenderingMode="ClearType" TextOptions.TextFormattingMode="Display"
                                                    LineHeight="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=LineHeight}"/>

                        <ScrollViewer x:Name="PART_ContentHost" />
                    </Grid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

重点是ControlTemplate。如您所见,HighlightTextBox的内容由TextCanvas和ScrollViewer组成。

HighlightTextBox通过在TextCanvas上绘画来突出显示当前选定的行,但它会如下所示侵入VerticalScrollViewer部分。

enter image description here

我想通过不入侵VerticalScrollViewer来显示它。

我认为原因可能是TextCanvas占据了TextBox的整个部分。因此,我尝试将TextCanvas移到ScrollViewer中,但是这种方式使运行时出现错误,即“ PART_ContentHost不能具有子元素。

我认为另一种方法是获取TextBox的内容宽度,而不是VerticalScrollBar的宽度,并将其绑定到TextCanvas的宽度。但我不知道该如何获得。

我应该怎么解决这个问题?如果您有更好的方法或其他解决方法,请告诉我。

谢谢您的阅读。

wpf controltemplate
1个回答
1
投票

Search the visual tree用于您的ScrollViewer的内容演示者,这将为您提供内容区域本身的宽度:

var scrollViewer = yourTextBox.Template.FindName("PART_ContentHost", yourTextBox) as ScrollViewer;
var contentPresenter = UIHelper.FindChild<ScrollContentPresenter>(scrollViewer, String.Empty);
var width = contentPresenter.ActualWidth;

更新:您可以像这样直接绑定到ScrollContentPresenter的内容控件:

<Grid Margin="{TemplateBinding Padding}" x:Name="PART_Grid">
    <TextBlock Text="{Binding ElementName=PART_ContentHost, Path=Content.ActualWidth}" Background="CornflowerBlue" VerticalAlignment="Top"/>
    <ScrollViewer x:Name="PART_ContentHost" />
</Grid>

请记住,尽管这为您提供了ScrollViewers的宽度content宽度,在上面的示例中,由于ScrollViewers的内容是一个具有2,0,2,0边距的TextBoxView:

enter image description here

为了补偿这一点,您可能需要将Canvas边距绑定到TextBoxView边距(在我的情况下是TextBlock而不是Canvas):

<Grid Margin="{TemplateBinding Padding}" x:Name="PART_Grid">
    <TextBlock Text="{Binding ElementName=PART_ContentHost, Path=Content.ActualWidth}"
               Margin="{Binding ElementName=PART_ContentHost, Path=Content.Margin}"
               Background="CornflowerBlue" VerticalAlignment="Top" />
    <ScrollViewer x:Name="PART_ContentHost" Padding="0" Margin="0"/>
</Grid>

这将使您的画布在父网格中的对齐方式与TextBoxView的对齐方式相同,以便所有内容正确对齐:

enter image description here

((您也可以只删除TextBoxView的边距,但这可能不是您想要的。)>

© www.soinside.com 2019 - 2024. All rights reserved.