0

我在自定义ControlTemplatefor aTextBox时遇到问题。这个想法是在尽可能少的用户交互的情况下自动在横格纸上整齐地打印文本,同时在文本长度、字体大小等方面保持尽可能灵活。

为此,一项设置​​是相对于打印行的文本高度(它在纸上显示的行距/高出多近/多远)。由于更改 TextBoxLineHeight会在文本下方而不是上方添加空间,因此我一直在文本框顶部使用 Padding 来向下翻译文本。

只要指定的 LineHeight 大于文本框内的剩余可见空间,就会出现问题。可能会无意中向下滚动到行的底部,导致文本向上滚动到填充区域并消失。

为了解决这个问题,我需要防止 MouseWheel/PgUp/PgDwn 在文本框内滚动,或者弄清楚如何沿着一行的底部边缘而不是顶部呈现文本。

使用 Snoop,我发现 TextBox 控件具有一个ScrollContentPresenter其 CanContentScroll 属性由它的 ParentTemplate 从一个ScrollViewer. 在应用程序运行时取消检查CanContentScrollSnoop 会禁用滚动并按照我的意愿阻止这种行为,但由于某种原因CanContentScroll = False,在模板中指定确实有效。它仍然存在True

XAML:

<TextBox.Style>
    <Style TargetType="TextBoxBase">
        . . . 
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type TextBoxBase}">
                    <theme:ListBoxChrome x:Name="Bd" . . . >
                        <ScrollViewer x:Name="PART_ContentHost"
                                      CanContentScroll="False"/>
                    </theme:ListBoxChrome>
                    . . . 
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</TextBox.Style>

该样式直接取自 Microsoft 的 WPFThemes/Aero.NormalColor.xaml,只需对 controltemplate 进行一次更改即可禁用滚动。对其他(省略的)设置器(例如背景颜色)的更改确实有效。我直接在 TextBox 中指定了样式,因为它不会在其他任何地方使用,并假设本地样式先于隐式样式,但我猜这可能不是执行此操作的正确位置。

谁能指出我在哪里出错了,或者确认是否可以更改文本在一行上的呈现位置?

谢谢

编辑:这是对这个 TextBox 实际在做什么的更好描述

假设您有一张纸质表格,例如贷款或许可申请,其中有几个问题,每个问题都有 3 行用于写下您的答案。文本框:

  • 大小/位置可覆盖整个答案区域
  • 设置为包含 3 行
  • 为用户提供字体大小、对齐方式、字体选项
  • 自动LineHeight均匀地调整间距线并设置Padding将文本定位在打印线的正上方
  • 不允许溢出,即使文本输入比预期的长。行数以倍数增加(双倍,然后是三倍,等等),并且调整字体大小以尝试在提供的空间中整齐地打印所有内容(例如,没有文本行被打印行划掉)

在实践中,这非常有效,并且可以生成整洁的表格,就好像有人用旧的 Selectric 手工完成的一样。唯一的问题是这种意外滚动问题偶尔会发生。

4

1 回答 1

1

在 Anatoliy 提醒我不会CanContentScroll启用或禁用内容滚动(尽管它的名称),而是在按像素滚动和按项目滚动之间切换后,我的问题的含义发生了变化。然而,我的意图是完全停止滚动行为,我现在已经解决了这个问题,并且还通过消除嵌套的 ScrollViewers 改进了托管它们的滚动行为:TextBoxListBox

首先,我发现这篇博文解释了为什么ScrollViewer总是处理MouseWheel. 可以对 ScrollViewer 进行子类化以防止这种情况发生,直到我想知道为什么我不能将模板中的内容宿主元素更改为不滚动的东西,因为我根本不需要它。 ContentPresenter没有用,但是这个 MSDN 页面上的重要说明框提到 TextBox 仅适用于ScrollVieweror AdornerDecorator

切换到AdornerDecorator完美工作:

<Setter Property="Template">
    <Setter.Value>
        <ControlTemplate TargetType="{x:Type TextBoxBase}">
            . . .
            <AdornerDecorator x:Name="PART_ContentHost"
                              ClipToBounds="True"
                              Margin="{Binding GetTextOffset}"
                              />
        </ControlTemplate>
    </Setter.Value>
</Setter>

我能够将边距绑定到我现有的文本偏移属性以像以前一样定位文本,并将ClipToBounds内容限制在可见区域。另一个主要改进是现在滚动浏览这些文本框的集合ListBox可以按预期工作,因为文本框不再处理 MouseWheel。嵌套的 ScrollViewers 令人不快。

于 2013-08-06T18:53:29.110 回答