I'm using a TreeView in WPF that has an explicit height set. The vertical scrollbar is cut off at the bottom (independent of whether items are bound/shown or not; I've enabled the scrollbar to be able to reproduce the problem without items attached). XAML source below.
<Window x:Class="demo.TreeViewProblem"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="..."
ResizeMode="CanResizeWithGrip"
SizeToContent="WidthAndHeight">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock
Grid.Column="0"
Grid.Row="0"
Margin="5,10,5,5"
Text="Some label"/>
<TextBlock
Grid.Column="1"
Grid.Row="0"
Margin="5,10,5,5"
Text="Some value"/>
<TreeView
ScrollViewer.VerticalScrollBarVisibility="Visible"
Grid.Column="1"
Grid.Row="1"
Height="200"
MinHeight="200"
Width="300"
Margin="5,10,5,5"
VerticalAlignment="Top" />
<TextBlock
Grid.Column="0"
Grid.Row="2"
Margin="5,10,5,5"
Text="Some label"/>
<TextBox
Grid.Column="1"
Grid.Row="2"
Width="80"
Margin="5,10,5,5"
HorizontalAlignment="Left"
Text="Some value"/>
<TextBlock
Grid.Column="0"
Grid.Row="3"
Margin="5,10,5,5"
Text="Some label"/>
<TextBox
Grid.Column="1"
Grid.Row="3"
Width="80"
Margin="5,10,5,5"
HorizontalAlignment="Left"
Text="Some value"/>
<Button
HorizontalAlignment="Center"
Margin="10,10,10,10"
Content="Close"
Grid.ColumnSpan="2"
Grid.Column="0"
Grid.Row="4"/>
</Grid>
</Window>
Change the RowDefinition for the row containing your TreeView to this:
<RowDefinition Height="Auto" />
When set to "Auto", the row will calculate how much space it needs.
EDIT: Alternatively, you could set the other rows to Auto and then make your TreeView stretch instead. With this approach your window will scale nicer when the user resizes it.
From the row definitions:
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
From the tree:
<TreeView VerticalAlignment="Stretch"
... />
Related
I have a very simple page with a header and several textboxes in my UWP app:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="Page Title!" />
<ScrollViewer Grid.Row="1" VerticalScrollMode="Auto">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBox Grid.Row="0" Margin="20" />
<TextBox Grid.Row="1" Margin="20" />
<TextBox Grid.Row="2" Margin="20" />
<TextBox Grid.Row="3" Margin="20" />
<TextBox Grid.Row="4" Margin="20" />
</Grid>
</ScrollViewer>
</Grid>
In Windows 10 mobile, when the bottom textbox get focus and soft keyboard appears, the full content of the page is scrolling up and I don't want this. I want the header to remain visible and the scrollviewer scrolls to the textbox to keep in view.
How can I achive this?
Thanks in advance.
You can use the CommandBar and add the TextBlock into CommandBar.Content, then the header will remain visible in the page. The page xaml code should look like this,
<Page.TopAppBar>
<CommandBar Background="Transparent" OverflowButtonVisibility="Collapsed">
<CommandBar.Content>
<TextBlock Text="Page Title!" Margin="20" />
</CommandBar.Content>
</CommandBar>
</Page.TopAppBar>
<Grid>
<ScrollViewer VerticalScrollMode="Auto">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBox Grid.Row="0" Margin="20" />
<TextBox Grid.Row="1" Margin="20" />
<TextBox Grid.Row="2" Margin="20" />
<TextBox Grid.Row="3" Margin="20" />
<TextBox Grid.Row="4" Margin="20" />
</Grid>
</ScrollViewer>
</Grid>
My goal is a TextBox that accepts return but only shows 4 lines of text that is alligned to other lines of text, but I'm having some problems that basically seem to boil down to the question: What is the correct way to get the content of a TextBox to vertically stretch to the available space?
A minimal example looks like this:
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="150" d:DesignWidth="150">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Label Grid.Column="0" Grid.Row="0" Content="1" />
<Label Grid.Column="0" Grid.Row="1" Content="2" />
<Label Grid.Column="0" Grid.Row="2" Content="3" />
<Label Grid.Column="0" Grid.Row="3" Content="4" />
<TextBox Grid.Column="1" Grid.Row="0" Grid.RowSpan="4" VerticalContentAlignment="Stretch" VerticalAlignment="Stretch" AcceptsReturn="True" MaxLines="4" Text="1
2
3
4" />
</Grid>
</Window>
But the output is not what I expected:
I tried setting the LineHeigt, but it only "cuts off" the text:
<TextBox Grid.Column="1" Grid.Row="0" Grid.RowSpan="4" VerticalContentAlignment="Stretch" VerticalAlignment="Stretch" AcceptsReturn="True" MaxLines="4" Text="1
2
3
4" TextBlock.LineStackingStrategy="MaxHeight" TextBlock.LineHeight="18" VerticalScrollBarVisibility="Visible" />
edit
Setting a fixed height for the TextBox corrects the behaviour, but that's not really a good way to solve the problem.
The immediate reason for your current issue is because you're using Label instead of TextBlock
The issue this causes is that TextBox renders lines as TextBlock which is a framework element. Whereas Label is a templated control inheriting from ContentControl and has a Padding set by default within it.
So if you you want them to align in your scenario you've got some options such as;
Curb the padding on your Label's;
<Label Padding="0"/>
Or swap them for good old TextBlock (which by the way is a "lighter" control and suggested instead unless using Label is actually necessary).
Or you could adjust your TextBox to reflect the padding of your Label's by targeting TextBlock with attached properties like TextBlock.LineHeight and TextBlock.LineStackingStrategy="BlockLineHeight" which would take some tinkering to get the exact output you want.
Also keep in mind TextBox is also a templated control with an embedded ScrollViewer so there will be a 1px offset for the default BorderThickness
So keeping your original control pairs if we do something like this instead, you'll see the culprit as example;
<Grid ShowGridLines="True"
HorizontalAlignment="Center" VerticalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Label Content="1" Padding="0"/>
<Label Grid.Row="1" Content="2" Padding="0"/>
<Label Grid.Row="2" Content="3" Padding="0"/>
<Label Grid.Row="3" Content="4" Padding="0"/>
<TextBox BorderThickness="0"
Grid.Column="1" Grid.RowSpan="4"
VerticalAlignment="Top"
VerticalContentAlignment="Stretch"
AcceptsReturn="True" MaxLines="4"
Text="1
2
3
4" />
</Grid>
Giving the result of;
Hope this helps, cheers.
A textbox could be stretched if it is inside a viebox, like this:
<Viewbox Stretch="Uniform" Grid.Column="1" Grid.Row="0" Grid.RowSpan="4" >
<TextBox Name="textBox" VerticalAlignment="Stretch" VerticalContentAlignment="Stretch" Text="1
2
3
4"/>
</Viewbox>
But in similar condition, I'd like to use a DataGrid
Just wrap the Textbox into Grid and set his MaxHeight to Infinity and his Height Value from that Grid:
<Grid x:Name="ValueTextBoxGrid" Grid.Row="1">
<TextBox
MaxHeight="Infinity"
Text="Your Text"
TextWrapping="Wrap"
Height="{Binding ElementName=ValueTextBoxGrid,
Path=ActualHeight}" />
</Grid>
Is it possible to have a scrolling (multiline) TextBox without explicitly setting the height? Here is my example code snippet:
<Grid Grid.Row="6"
Grid.Column="2"
Grid.ColumnSpan="2">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Label Grid.Row="0">Heading</Label>
<TextBox Grid.Row="1"
SpellCheck.IsEnabled="True"
TextWrapping="Wrap"
AcceptsReturn="True"
VerticalScrollBarVisibility="Auto"></TextBox>
</Grid>
The problem here is that the TextBox will resize itself depending on how many lines the user enters without resorting to instead staying the same size and scrolling.
Simply add VerticalAlignment="Top"
<Grid Grid.Row="6"
Grid.Column="2"
Grid.ColumnSpan="2">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Label Grid.Row="0">Heading</Label>
<TextBox
VerticalAlignment="Top"
Grid.Row="1"
SpellCheck.IsEnabled="True"
TextWrapping="Wrap"
AcceptsReturn="True"
VerticalScrollBarVisibility="Auto"></TextBox>
</Grid>
This will get you started. As you have not put your requirements clearly, it's difficult to put a proper solution. If you put your more clear requirements, I can make a better version for you.
<Window ...>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="476*"/>
<ColumnDefinition Width="45*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="8*"/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBox x:Name="textBox" HorizontalAlignment="Left" Width="{Binding Value, ElementName=HorizontalSB}" Height="{Binding Value, ElementName=VerticalSB}" Margin="30,37,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" />
<ScrollBar x:Name="VerticalSB" Grid.Column="1" HorizontalAlignment="Center" Width="Auto" SmallChange="1" Minimum="50" Value="25" MaxHeight="250" Maximum="1000"/>
<ScrollBar x:Name="HorizontalSB" Grid.Row="1" VerticalAlignment="Top" Width="Auto" Orientation="Horizontal" VerticalContentAlignment="Center" SmallChange="10" Maximum="1000" Minimum="20" LargeChange="10" Value="75"/>
</Grid>
</Window>
I've the following xaml definition. The textblock inside the stackpanel is not wrapping.
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<toolkit:PhoneTextBox x:Name="NotesText" Grid.Row="0" Grid.ColumnSpan="2" Hint="Add Notes" AcceptsReturn="True" Height="290" VerticalScrollBarVisibility="Auto" TextWrapping="Wrap" />
<StackPanel Orientation="Horizontal" Grid.Row="1" Grid.Column="0" >
<CheckBox x:Name="showRequester" FontSize="{StaticResource PhoneFontSizeSmall}" HorizontalAlignment="Left" />
<TextBlock TextWrapping="Wrap" VerticalAlignment="Center" HorizontalAlignment="Left" Text="option_show_to_requester" />
</StackPanel>
<CheckBox Grid.Row="1" Grid.Column="1" Content="Mail To Technicain" FontSize="{StaticResource PhoneFontSizeSmall}" HorizontalAlignment="Right" />
</Grid>
What I should do to make it wrap ? Thanks.
Update:
Problem with the alignment when using data template for check box content.
You can solve this by Providing Width of TextBlock.
You don't need to put a checkBox and a TextBlock into a StackPanel. To make the CheckBox's content Wrap, just use ContentTemplate of CheckBox.
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<toolkit:PhoneTextBox x:Name="NotesText" Grid.Row="0" Grid.ColumnSpan="2" Hint="Add Notes" AcceptsReturn="True" Height="290" VerticalScrollBarVisibility="Auto" TextWrapping="Wrap" />
<!--Use ContentTemplate of CheckBox-->
<CheckBox Grid.Row="1" Grid.Column="0">
<CheckBox.ContentTemplate>
<DataTemplate>
<TextBlock Text="option_show_to_requester" TextWrapping="Wrap"/>
</DataTemplate>
</CheckBox.ContentTemplate>
</CheckBox>
<CheckBox Grid.Row="1" Grid.Column="1" Content="Mail To Technicain" FontSize="{StaticResource PhoneFontSizeSmall}" HorizontalAlignment="Right" />
</Grid>
for a simple example:
<Grid Grid.Row="1" x:Name="ContentRoot" Tapped="ContentRoot_Tapped">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<CheckBox Grid.Column="0">
<CheckBox.ContentTemplate>
<DataTemplate>
<TextBlock TextAlignment="Center" Text="wrap123123123123wrap" TextWrapping="Wrap"/>
</DataTemplate>
</CheckBox.ContentTemplate>
</CheckBox>
<CheckBox Grid.Column="1">
<CheckBox.ContentTemplate>
<DataTemplate>
<TextBlock Text="nowrap" TextWrapping="Wrap"/>
</DataTemplate>
</CheckBox.ContentTemplate>
</CheckBox>
</Grid>
And the run image is:
I have a expander which contains a grid in which I have a grid splitter.
The Document Outline and UI is like this
and here is the code.
<Grid x:Name="TopGrid" ShowGridLines="True" >
<Grid.RowDefinitions>
<RowDefinition Height="Auto" MaxHeight="150"/>
<RowDefinition Height="200" />
</Grid.RowDefinitions>
<Expander x:Name="CompanyDescriptionExpander" Grid.ColumnSpan="2"
VerticalAlignment="Top" IsExpanded="True" Background="Black" >
<Expander.Header>
<Grid Width="{Binding ElementName=CompanyDescriptionExpander,
Path=ActualWidth}" Background="Aquamarine">
<TextBlock Grid.Column="0" Text="Expander Header" Foreground="Black" />
</Grid>
</Expander.Header>
<Expander.Content>
<Grid x:Name="DescriptionGrid" MaxHeight="130" ShowGridLines="True">
<Grid.RowDefinitions>
<RowDefinition Height="*" MinHeight="25" MaxHeight="25"/>
<RowDefinition Height="Auto" MinHeight="25" MaxHeight="120"/>
<RowDefinition Height="4" MinHeight="10" MaxHeight="10"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0" Background="Orange" Grid.Row="0" Grid.RowSpan="2"
MinHeight="40" MaxHeight="120" x:Name="DescriptionText"
Text="TextBlock Content" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Top"
HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Auto" />
<Button x:Name="SaveIconButton" Grid.Column="1" Grid.Row="0" Width="20"
Height="20" VerticalAlignment="Top" />
<Button x:Name="CancelIconButton" Grid.Column="1" Grid.Row="1" Width="20"
Height="20" VerticalAlignment="Top" />
<GridSplitter ResizeBehavior="PreviousAndCurrent" ResizeDirection="Rows"
Grid.Row="2" Grid.ColumnSpan="2"
Height="10" MaxHeight="10" HorizontalAlignment="Stretch"
VerticalAlignment="Top" Background="Red" />
</Grid>
</Expander.Content>
</Expander>
<Button Grid.Row="1" Grid.Column="0" Margin="0,5,0,0" Height="20"
VerticalAlignment="Top" Background="Green" />
</Grid>
When we use grid splitter it expands
But it goes on even after textbox reaches its maximum height and gridsplitter goes behind button(green).
My problem scenario can be replicated copying my code in a project
I want that it should stop when textbox reaches its maximum height.
How to do that?
In your DescriptionGrid change the second rows MaxHeight from 120 to 95.
The combined max height of the three rows in that grid exceeds the max height of the grid itself.