我知道在WPF中自动调整文本框大小有很多问题,但我找不到解决以下问题的方法。
考虑这个简单的窗口:
<Window x:Class="TestVisualBrush.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="470" Width="608">
<ScrollViewer>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBox>Test</TextBox>
<TextBox MinHeight="100" Grid.Row="1" AcceptsReturn="True" >Test</TextBox>
</Grid>
</ScrollViewer>
</Window>
这实现了我需要的这两个约束:
ScrollViewer
内容所需的最小尺寸而言太小,则ScrollViewer
会显示滚动条。但是,当您在第二个文本框中输入太多文字时,ScrollViewer
会显示滚动条,而不会显示TextBox
。我想停止文本框的高度增加超出父Grid
最初给出的空间。在这种情况下,我无法使用MaxHeight
,因为没有合适的ActualHeight
可以绑定(据我所见)。
有关如何解决此问题的任何建议(最好没有代码隐藏)?
在HTML中,我想要的内容将转化为:
<table height="100%">
<tr>
<td><input type="text"></td>
</tr>
<tr height="100%">
<td>
<!-- Uses as much space as it gets, but scrolls if text inside
gets too large. Makes outer window scroll if too small
for min-height and other controls in table. -->
<textarea style="height:100%;min-height:100px"></textarea>
</td>
</tr>
</table>
答案 0 :(得分:6)
可滚动扩展控制问题。
Scrollable-expandable-controls:控件可以随着内容的增长而拉伸,并在其大小受限时显示滚动条。
当它们位于另一个可滚动控件内时会出现问题。子可滚动扩展控件将继续扩展,并将依赖于外部可滚动控件的滚动条。
如果你给它一个最大宽度或高度问题将被解决,但你需要知道前面的尺寸,如果你想要一个适用于所有不同屏幕尺寸的动态应用程序,你就没有这个特权。
为了实现所需的行为,我们需要在它们之间使用一个面板来允许它的子节点(可滚动扩展控件)增长,要求它们提供所需的最小大小,然后为它们提供父节点提供的最大大小而不显示滚动条,目前没有这样的面板。
这是我开发的用于提供此功能的一个:
class LimitChild : System.Windows.Controls.Panel
{
public LimitChild()
{
}
protected override Size MeasureOverride(System.Windows.Size availableSize)
{
System.Diagnostics.Debug.Assert(InternalChildren.Count == 1);
System.Windows.UIElement child = InternalChildren[0];
Size panelDesiredSize = new Size();
// panelDesiredSize.Width = availableSize.Width;
panelDesiredSize.Width = (double)child.GetValue(FrameworkElement.MinWidthProperty);
panelDesiredSize.Height = (double)child.GetValue(FrameworkElement.MinHeightProperty);
child.Measure(panelDesiredSize);
// IMPORTANT: do not allow PositiveInfinity to be returned, that will raise an exception in the caller!
// PositiveInfinity might be an availableSize input; this means that the parent does not care about sizing
return panelDesiredSize;
}
protected override System.Windows.Size ArrangeOverride(System.Windows.Size finalSize)
{
System.Windows.UIElement child = InternalChildren[0];
child.Arrange(new Rect(0, 0, finalSize.Width, finalSize.Height));
if (finalSize.Width > child.RenderSize.Width)
finalSize.Width = child.RenderSize.Width;
if (finalSize.Height > child.RenderSize.Height)
finalSize.Height = child.RenderSize.Height;
return finalSize; // Returns the final Arranged size
}
}
然后在你的xaml里面封装你的可滚动扩展控件。
<l:LimitChild
Grid.Row="1">
<TextBox
VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Auto"
MinHeight="200"
AcceptsReturn="True">Test</TextBox>
</l:LimitChild>
答案 1 :(得分:2)
试试这个:
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBox />
<TextBox AcceptsReturn="True" Grid.Row="1" VerticalScrollBarVisibility="Auto" />
</Grid>
</Window>
这应该完全符合您的要求。
答案 2 :(得分:1)
试试这个:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBox Height="50"/>
<TextBox Grid.Row="1" AcceptsReturn="True" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Auto" />
</Grid>
你完成了:)
答案 3 :(得分:1)
沿着该行的某处,您必须设置启用滚动的文本框的最大高度。通常*会这样做,但因为它包含在滚动查看器中,所包含的网格没有有效的最大值。 您可以像这样使用MultiValueConverter
public class MaxHeightConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
double result = (double)values[0];
for (int n = 1; n < values.Length; ++n)
{
result = result - (double)values[n];
}
return result;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
然后您的XAML将如下所示
<Window x:Class="wpf_Hacks.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:wpf_Hacks"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:MaxHeightConverter x:Key="maxHeightConverter"></local:MaxHeightConverter>
</Window.Resources>
<ScrollViewer>
<Grid x:Name="rootGrid">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBox x:Name="headerTextBox" Height="50" Text="Textbox 1"/>
<TextBox MinHeight="100" Grid.Row="1" AcceptsReturn="True" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Auto" Text="Textbox 2">
<TextBox.MaxHeight>
<MultiBinding Converter="{StaticResource maxHeightConverter}">
<Binding ElementName="rootGrid" Path="ActualHeight"></Binding>
<Binding ElementName="headerTextBox" Path="ActualHeight"></Binding>
</MultiBinding>
</TextBox.MaxHeight>
</TextBox>
</Grid>
</ScrollViewer>
基本上,多值转换器将第一个绑定值作为可用的总高度,然后将其减少其他绑定元素的高度,留下最终文本框的剩余空间
希望这有帮助
答案 4 :(得分:0)
实际上,您可以使用RelativeSource
绑定访问祖先来绑定ActualHeight
:
Height="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Grid}},
Path=RowDefinitions[1].ActualHeight}"
<小时/> 更新
如果您只为秒 TextBox
显示该滚动条的内容 - 仅为其添加ScrollViewer
:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBox>Test</TextBox>
<ScrollViewer Grid.Row="1">
<TextBox MinHeight="100" AcceptsReturn="True" >Test</TextBox>
</ScrollViewer>
</Grid>
答案 5 :(得分:0)
我想出了类似的东西,但是我还在测试,只需要知道这是不是你想象的那样?
<Window x:Class="testWpf.WindowTextBoxInnerScroll"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="200" Width="608" Name="MyWindow" Loaded="MyWindow_Loaded">
<ScrollViewer VerticalScrollBarVisibility="Auto" >
<Grid name="MyGrid">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBox>Test</TextBox>
<TextBox Name="TB2" Grid.Row="1" MinHeight="100" TextWrapping="Wrap"
VerticalScrollBarVisibility="Auto" AcceptsReturn="True" >Test</TextBox>
</Grid>
</ScrollViewer>
背后的代码
private void MyWindow_Loaded(object sender, RoutedEventArgs e)
{
if (this.Height > MyGrid.RowDefinitions[0].ActualHeight + MyGrid.RowDefinitions[1].ActualHeight)
{
TB2.Height = MyGrid.RowDefinitions[1].ActualHeight;
}
else
{
TB2.Height = TB2.MinHeight;
}
}
<强>更新强>
如果这不是你想要的,那么我不确定你对这个问题的期望是什么。
希望这有帮助。
更新2
我已经更新了我的XAML和Code,这对我有用。 (我想)。