防止WPF中的TextBox水平扩展

vnzz0bqm  于 2023-05-08  发布在  其他
关注(0)|答案(8)|浏览(207)

我在App.xaml中定义了以下样式

<Style x:Key="textBoxMultiline" TargetType="{x:Type TextBox}" >
    <Setter Property="VerticalScrollBarVisibility" Value="Auto" />
    <Setter Property="HorizontalScrollBarVisibility" Value="Hidden" />
    <Setter Property="MinHeight" Value="50" />
    <Setter Property="TextWrapping" Value="Wrap" />
</Style>

在整个解决方案中,我们在每个需要简短文本的文本框上使用它。

<TextBox x:Name="textBoxDescription" Grid.Row="2" Grid.Column="1" Style="{DynamicResource textBoxMultiline}" />

一切都很好,但是客户端抱怨一些字段在分辨率较低的旧显示器上被压缩,所以我在一个较高的可视化树节点上放置了一个ScrollViewer来防止压缩。

<ScrollViewer Height="Auto" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
   ...
</ScrollViewer>

奇怪的是,具有上述样式的TextBox es开始向右扩展,而不是环绕文本。
有没有办法在不删除ScrollViewer的情况下防止这种情况?

1zmg4dgp

1zmg4dgp1#

如果你不想硬编码宽度,那么你可以使用元素绑定父项的宽度。
在这里,我将TextBox MaxWidth与ScrollViewer的实际宽度绑定。您还必须确保ColumnDefinition宽度应设置为“*”而不是“Auto”。如果设置为自动,它将忽略ScrollViewer的宽度,并继续扩展ScrollViewer和TextBox的宽度。我觉得你在这件事上...

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"></ColumnDefinition>
        <ColumnDefinition Width="*"></ColumnDefinition>
    </Grid.ColumnDefinitions>
    <ScrollViewer HorizontalScrollBarVisibility="Auto" Name="scv">
        <TextBox Height="30" TextWrapping="Wrap" MaxWidth="{Binding ElementName=scv, Path=ActualWidth}"></TextBox>
    </ScrollViewer>
</Grid>
fwzugrvs

fwzugrvs2#

必须为TextBox定义一个MaxWidth,否则没有限制,因为ScrollViewer

pes8fvy9

pes8fvy93#

@bathineni提供的解决方案帮助我解决了我的问题。以下是对我有效的方法:

<Grid >
    <Grid.ColumnDefinitions>
    <ColumnDefinition Width="50"/>
    <ColumnDefinition  Width="*"/>
</Grid.ColumnDefinitions>
    <Button Grid.Column="0" Width="30" Height="23" Margin="10,5" Content="..."/>
    <ScrollViewer  Grid.Column="1" HorizontalScrollBarVisibility="Disabled" verticalScrollBarVisibility="Disabled" Name="scv">
         <TextBox Height="25" Text="Insert here long text" MaxWidth="{Binding ElementName=scv, Path=ActualWidth}" HorizontalAlignment="Stretch" />
    </ScrollViewer>
</Grid>
mm9b1k5b

mm9b1k5b4#

我尝试了前面提到的例子,它们不起作用,所以我自己解决了这个问题。有两种方法可以解决这个问题:
第一种解决方案是使用数据绑定在XAML中实现的。我建议你不要自己绑定控件。XAML解决方案是通过将具有所需ActualWidth和ActualHeight属性的控件绑定到文本框MaxHeight和MaxWidth属性来实现的。

<TextBlock x:Name="PasswordText" Margin="0,0,0,20" FontFamily="Bahnschrift SemiBold Condensed" Text="PASSWORD" FontSize="20"> 

 
<TextBox x:Name="PasswordTextBox" MaxWidth="{Binding ElementName=PasswordText, Path=ActualWidth}" MaxHeight="{Binding ElementName=PasswordText, Path=ActualHeight}">

下一个解决方案是通过在XAML中生成Loaded事件,在C#代码中创建它,然后在Loaded事件中将文本框的MaxWidth和MaxHeight属性设置为文本框ActualWidth和ActualHeight属性来实现的。

//  It doesn't have a problem like in XAML if you pass the textbox its own   
//  ActualWidth and ActualHeight to the MaxWidth and MaxHeight proprieties. 

        private void Log_In_Page_Loaded(object sender, RoutedEventArgs e)
        {
            UsernameTextBox.MaxHeight = UsernameTextBox.ActualHeight;
            UsernameTextBox.MaxWidth = UsernameTextBox.ActualWidth;
        }

选择一个更适合你的设计,但我认为,在我看来,这是解决这个问题的最有效,简单,稳定和有效的方法。

agyaoht7

agyaoht75#

对我来说很好如果您希望滚动条出现在文本框中,您可以添加

HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"

到文本框

yrdbyhpb

yrdbyhpb6#

必须设置Container ControlMaxWidth

<Grid x:Name="RootGrid" Margin="6,6,8,8" Width="500" MaxWidth="500">
<ScrollViewer ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Auto">
  <Grid>
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <GroupBox Name="contentGroup" Header="Content" Grid.Row="0">
      <TextBox Name="content"/>
    </GroupBox>
  </Grid>
</ScrollViewer>
kwvwclae

kwvwclae7#

我遇到了这个问题,当我需要我的TextBox与它的自动调整大小的Grid列沿着拉伸时,它被调整大小,这意味着MaxWidth将无法工作,但仍然需要防止TextBox与它的内容一起拉伸。
我最终做的是将这个事件处理程序链接到SizeChanged

private void TextBox_SizeChanged(object sender, SizeChangedEventArgs e) {
    TextBox textBox = (TextBox)sender;
    if (textBox.CanUndo && e.NewSize.Width > e.PreviousSize.Width) {
        textBox.Width = e.PreviousSize.Width;
    }
}

向文本框中写入文本是用户可以撤销的,而其他可能导致调整大小的操作(元素的初始绘制,父容器的拉伸等)则无法从文本框中撤销。因此,通过检查CanUndo,我们可以确定SizeChanged是由写入文本还是其他内容触发的。
e.NewSize.Width > e.PreviousSize.Width检查是必要的,因为如果没有它,SizeChanged事件将被无限地从自身内部调用,因为要恢复拉伸,我们需要 * 将大小 * 更改回原始值,这本身将触发事件。
这是一个小黑客,但我还没有遇到任何问题。

63lcw9qa

63lcw9qa8#

我不知道为什么,但我不能让ScrollViewer解决方案工作。我需要有一个固定初始宽度的TextBox来实现一个数字向上/向下控件-在这个控件中,TextBox独立于输入而收缩和增长,如果UI随着您的输入而变化,这看起来非常烦人。
所以,我发现下面的解决方案使用2文本框为我工作。第一个文本框是显示给用户以键入其输入的文本框,第二个文本框通过依赖性属性(DisplayLength)和下面进一步示出的转换器初始化。
将第一个文本框的MaxWidth属性绑定到第二个文本框的Width属性可以固定大小,这样用户可以键入他们想要的内容,但即使有更多的UI空间可用,文本框的显示宽度也不会更改。

<TextBox x:Name="PART_TextBox"
    Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Value}"
    Margin="0,0,1,0"
    TextAlignment="Right"
    AcceptsReturn="False"
    SpellCheck.IsEnabled="False"
    HorizontalContentAlignment="Stretch"
    VerticalContentAlignment="Center"
    HorizontalAlignment="Stretch"
    VerticalAlignment="Stretch"
    MaxWidth="{Binding ElementName=TBMeasure, Path=ActualWidth}"
    />

<!-- Hidden measuring textbox ensures reservation of enough UI space
     according to DisplayLength dependency property
-->
<TextBox x:Name="TBMeasure"
    Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=DisplayLength, Converter={StaticResource ByteToPlaceHolderStringConverter}}"
    Margin="0,0,1,0"    
    TextAlignment="Right"
    AcceptsReturn="False"
    SpellCheck.IsEnabled="False"
    HorizontalContentAlignment="Right"
    VerticalContentAlignment="Center"
    HorizontalAlignment="Stretch"
    VerticalAlignment="Stretch"
    Visibility="Hidden"/>


// Converter
[ValueConversion(typeof(byte), typeof(string))]
public sealed class ByteToPlaceHolderStringConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if ((value is byte) == false)
            return Binding.DoNothing;

        byte byteVal = (byte)value;

        string retString = string.Empty;
        for (int i = 0; i < byteVal; i++)
            retString = retString + "X";

        return retString;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return Binding.DoNothing;
    }
}

相关问题