TextLineBounds snipping bottom of letters - xaml

I'm using TextLineBounds in Windows 8.1 to align text of different font sizes on the baseline, such as
With the XAML looking like:
<Grid x:Name="PageHeader">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="28" />
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="15" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="15" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="1"
VerticalAlignment="Bottom"
TextLineBounds="TrimToBaseline"
FontSize="50"
Text="OOO Big Font" />
<TextBlock Grid.Column="3"
VerticalAlignment="Bottom"
TextLineBounds="TrimToBaseline"
FontSize="26"
Text="OOO SmallerFont" />
<TextBlock Grid.Column="5"
VerticalAlignment="Bottom"
TextLineBounds="TrimToBaseline"
FontSize="20"
Text="OOO Even Smaller Font" />
</Grid>
</Grid>
When I resize the window, at some point (before the minimum size of 500) the descenders are clipped (and I've also seen the bottom pixel or two across entire line get clipped even when there are no descenders - resulting in artifacts like a flattened O).
The display elements do not change on the resize, there's no modification due to visual state, etc.
It seems like a bug, but not sure if there's a workaround (other than to abandon use of TextLineBounds).

Related

ListView gets not scrollable

I have a proble which seems pretty common and has been asked alot, but I can't find a fixing solution for my problem.
So I try to use 3 listviews in in one page all shall have a title and an explaining image, but instead of designing all 3 ListViews in one page I outsourced one listview with image and title into a control, which I use in my page.
The 3 Controls are placed in a grid. When the listview items get filled thy scrollbar should become visible if the remaining space is no longer enough but it won't show.
I provided a sandbox project where I placed the control and etc. like in the application I'm working on. SampleProject
Their you just need to press start and the listviews get filled. But they don't show the scrollbar.
Thanks in advance!
Edit 1:
As requested I share my code below. If you open up the sample project then you do not need to read further until a second edit is done.
Control containing listview:
<Grid>
<Grid x:Name="Section"
HorizontalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid x:Name="grdTitleArea"
HorizontalAlignment="Stretch"
Height="50">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<BitmapIcon
VerticalAlignment="Center"
HorizontalAlignment="Center"
Tapped="grdTitleArea_Tapped"
UriSource="ms-appx:///Assets/area.png"
Height="40" />
<TextBlock
VerticalAlignment="Center"
HorizontalAlignment="Stretch"
Tapped="grdTitleArea_Tapped"
Text="Area"
Grid.Column="1" />
</Grid>
<!--<ScrollViewer
VerticalAlignment="Stretch"
VerticalScrollBarVisibility="Auto"
VerticalScrollMode="Enabled"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
HorizontalScrollBarVisibility="Hidden"
HorizontalScrollMode="Disabled"
>-->
<ListView x:Name="ListView"
ScrollViewer.VerticalScrollBarVisibility="Visible"
ScrollViewer.VerticalScrollMode="Auto"
Grid.Row="1">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<Grid
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
BorderThickness="1"
Margin="1"
Height="50">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding ActionDescription}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<!--</ScrollViewer>-->
</Grid>
</Grid>
Control which contains the control above 3 times:
<Grid x:Name="ProgressControl">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<local:SynchronizeSettingsControl
Visibility="Visible"
x:Name="Settings" />
<local:SynchronizeSectionControl
x:Name="ActualAction"
Visibility="Visible"
Grid.Row="1" />
<local:SynchronizeSectionControl
x:Name="Error"
Visibility="Visible"
Grid.Row="2" />
<local:SynchronizeSectionControl
x:Name="Log"
Visibility="Visible"
Grid.Row="3" />
</Grid>
Page which contains the control which contains the listview:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="50" />
<RowDefinition Height="*" />
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="1"
Text="Demo"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Grid>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Grid.Column="0" Width="70"
VerticalAlignment="Stretch"
Content="Useless Button" />
</Grid>
<Controls:SynchronizeControl
x:Name="ctlSync"
Grid.Row="2"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch" />
<Button VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
x:Name="btnStart"
Content="Start"
Tapped="btnStart_Tapped"
Grid.Row="3" />
</Grid>
The problem is you used Auto height in the page. This means basically that the page tells the local:SynchronizeSectionControl control: "You can use whichever height you want".
The control then has * as the height of the second row which means "use the rest space available". But because the page offered essentially "infinite height", the ListView height will stretch as much as possible to accommodate for all its items and hence it doesn't scroll, as its height is big enough to display everything, although it is cut off and not visible, because the window height is of course limited.
The thing is you used the Auto property for the height of your rows in your control.
This works fine is the control you use uses a definite space. Like a button or similar stuff. But when the control can extend indefinitely the allocation for the space gets screwed up.
Basically the control displays at its maximum size but extends way over its boundaries.
You can prevent that when you use the * as a Height value.
This will lead to the control taking up all the space available. You can further limit this with using the MaxHeight property.
If you do it that way it will display a scrollviewer when necessary and it will even resize when you change the window size.

Making fixed-width grid columns and rows in UWP

I am making an application and I want certain grid rows and columns to be fixed, while others resize to fit the window. My problem is that I cannot do this in Universal Apps.
In WPF, the solution is simple:
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="50" /> <!-- This row is a fixed height -->
<RowDefinition Height="*" MinHeight="200" /> <!-- This row is resizeable, but has a minimum height -->
<RowDefinition Height="100" />
<RowDefinition Height="20" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20" /> <!-- This column has a fixed width -->
<ColumnDefinition Width="*" MinWidth="300" /> <!-- These rows are resizeable, but have minimum widths -->
<ColumnDefinition Width="*" MinWidth="300" />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
</Grid>
When I try this in UWP, the rows and columns with fixed sizes resize while the others with asterisks stay fixed. I tried putting asterisks on the fixed rows and columns and removing the pre-existing ones. I thought that in UWP it was reversed, however this severely messed up my app and made it worse.
My solution was to try the following in UWP:
<Grid x:Name="pageGrid"
Background="White">
<Grid.RowDefinitions>
<RowDefinition MaxHeight="20"
MinHeight="20"/>
<RowDefinition Height="*"/>
<RowDefinition MaxHeight="20"
MinHeight="20"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition MaxWidth="20"
MinWidth="20"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition MaxWidth="260"
MinWidth="260"/>
<ColumnDefinition MaxWidth="20"
MinWidth="20"/>
</Grid.ColumnDefinitions>
</Grid>
The idea here is to have fixed margins around my controls, at 20 pixels width. Inside these margins there are two boxes: One has a fixed width and resizable height, and the other resizes in both directions.
Despite this, I again experienced the same problem where the margins resize but the 'resizable' boxes do not.
Is there actually a way to have fixed and resizeable rows and columns in a grid using Universal Windows Platform? So far, i have yet to find evidence of this.
Complete code:
<Page
x:Class="UniversalCamera.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:UniversalCamera"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
MinWidth="800"
MinHeight="450"
Width="800"
Height="450">
<Grid x:Name="pageGrid"
Background="White">
<Grid.RowDefinitions>
<RowDefinition MaxHeight="20"
MinHeight="20"/>
<RowDefinition Height="*"/>
<RowDefinition MaxHeight="20"
MinHeight="20"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition MaxWidth="20"
MinWidth="20"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition MaxWidth="260"
MinWidth="260"/>
<ColumnDefinition MaxWidth="20"
MinWidth="20"/>
</Grid.ColumnDefinitions>
<Border BorderThickness="2"
BorderBrush="Black"
CornerRadius="5"
Grid.Column="1"
Grid.Row="1"
Grid.ColumnSpan="2"
Margin="-10,-10,-10,-10"/>
<Border BorderThickness="2"
BorderBrush="Black"
CornerRadius="5"
Grid.Column="1"
Grid.Row="1"
Margin="2,2,2,2">
<Image x:Name="imageFrame"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"/>
</Border>
<Canvas x:Name="controlCanvas"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Grid.Column="2"
Grid.Row="1">
<StackPanel x:Name="controlStack"
Canvas.Top="0"
Canvas.Left="0"
Width="260"
Orientation="Vertical">
<Button x:Name="startLiveButton"
Width="200"
Margin="0,5,0,0"
HorizontalAlignment="Center"
Content="Start Live"
Click="startLiveButton_Click"/>
<Button x:Name="stopLiveButton"
Width="200"
Margin="0,5,0,0"
HorizontalAlignment="Center"
Content="Stop Live"
Click="stopLiveButton_Click"/>
<Button x:Name="freezeVideoButton"
Width="200"
Margin="0,5,0,0"
HorizontalAlignment="Center"
Content="Freeze Video"
Click="freezeVideoButton_Click"/>
<Button x:Name="loadParameterButton"
Width="200"
Margin="0,5,0,0"
HorizontalAlignment="Center"
Content="Load Parameter"
Click="loadParameterButton_Click"/>
<CheckBox x:Name="autoWhiteCheckbox"
HorizontalAlignment="Center"
Width="200"
Margin="0,25,0,0"
Content="Auto White Balance"
Checked="autoWhiteCheckbox_Checked"
Unchecked="autoWhiteCheckbox_Unchecked"/>
<CheckBox x:Name="autoGainCheckbox"
HorizontalAlignment="Center"
Width="200"
Margin="0,5,0,0"
Content="Auto Gain Balance"
Checked="autoGainCheckbox_Checked"
Unchecked="autoGainCheckbox_Unchecked"/>
</StackPanel>
</Canvas>
</Grid>
</Grid>
</Page>
This code is intended to have extra rows and columns as margins around the main controls. These should be fixed at 20 pixels. When I run the code the margins stretch and the central boxes stay fixed; this is the opposite of what I intended:
(The black outlined area stays the same size when the window is resized while the margins stretch to fit the window.)
Your main Grid is fixed at 800 x 450 px. If you remove that restriction, the grid will stretch appropriately
Updated code:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
MinWidth="800"
MinHeight="450">
<Grid x:Name="pageGrid"
...

Grid adding unwanted extra vertical space

I have the following xaml inside a user control:
<StackPanel VerticalAlignment="Top">
<Grid Background="LimeGreen">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Rectangle Grid.Column="0" Grid.Row="0" Grid.RowSpan="3" VerticalAlignment="Top" Fill="Yellow" Width="80" Height="80" />
<Rectangle Grid.Column="1" Grid.Row="0" VerticalAlignment="Top" Fill="Red" Width="10" Height="10" />
<Rectangle Grid.Column="1" Grid.Row="1" VerticalAlignment="Top" Fill="Red" Width="10" Height="10" />
<Rectangle Grid.Column="1" Grid.Row="2" VerticalAlignment="Top" Fill="Red" Width="10" Height="10" />
</Grid>
</StackPanel>
and it produces the following layout:
For some reason, this is adding extra unwanted space after the yellow square. I want the following layout instead:
The extra space only occurs when the green grid is inside a stack panel. I can get the correct layout by either:
Putting the green grid inside a grid instead of a stack panel.
Or setting the width of the second column to "Auto". This is undesired, though.
My questions are:
Is the layout in the first picture correct/expected? If so, why is it adding the extra space?
Why does setting the width of the second column to "Auto" get rid of the extra vertical space?
How can I get layout #2 inside a stack panel with width of second column set to * (star)?
I can answer question 3 with this alternative xaml, however it uses a nested grid to bypass using a row span for the yellow square. Ideally this should be possible using just one grid. Anyway, here's the xaml:
<StackPanel VerticalAlignment="Top">
<Grid Background="LimeGreen">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Rectangle VerticalAlignment="Top" Fill="Yellow" Width="80" Height="80" />
<Grid Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Rectangle Grid.Row="0" VerticalAlignment="Top" Fill="Red" Width="10" Height="10" />
<Rectangle Grid.Row="1" VerticalAlignment="Top" Fill="Red" Width="10" Height="10" />
<Rectangle Grid.Row="2" VerticalAlignment="Top" Fill="Red" Width="10" Height="10" />
</Grid>
</Grid>
</StackPanel>
I'm still stumped on answering questions 1 and 2.

Textblock and HyperlinkButton do not align correctly

I'd like to have a hyperlink and a textblocks on the same line, however both controls act somewhat different. The hyperlink is just a few pixels more to the right, like there is a margin but it's not, is it? Just look at this piece of code:
<UserControl x:Class="SilverlightApplication7.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Grid.Row="2" Text="Umsatzsteuerart: " />
<TextBlock Grid.Row="2" Grid.Column="1" Text="Test" />
<TextBlock Grid.Row="3" Grid.Column="0" Text="Hersteller:" />
<HyperlinkButton Grid.Row="3" Grid.Column="1" Content="Test" />
<TextBlock Grid.Row="4" Grid.Column="0" Text="Umsatzsteuerart:" />
<TextBlock Grid.Row="4" Grid.Column="1" Text="Test" />
</Grid>
</UserControl>
Shouldn't all three ui-controls be aligned to the same line? Is there a solution for this problem? HorizontalAlignment doesn't effect anything...
Found the solution myself:
Setting the padding of the HyperlinkButton will align the hyperlink correctly.

XAML - Can't resize elements to 0 width in this case

Given the following XAML my goal is to keep the columns AAA, BBB, CCC always visible. The columns with the listboxes can resize all the way to zero though.
If I remove the ListBoxes then the application works exactly the way I want it to. That is, it doesn't have the weird behavior where the min widths are not respected.
With the listboxes (or DataGrids) the following XAML has this behavior:
After starting the application, if I drag the splitterA all the way close to BBB (BBB will keep the desired width of 25), then drag the splitterB all the way to the right then AAA will have the desired width of 25.
On the other hand, after starting the application, if I drag splitterA all the way to the right (AAA will keep the desired width of 25), then drag the splitterB all the way to the right then AAA will go off the screen. Surprisingly if I then drag the splitterA just a pixel to the left then both columns will "snap" into the correct place.
<Grid Background="CadetBlue" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition />
<ColumnDefinition MinWidth="60"/>
</Grid.ColumnDefinitions>
<TextBlock Text="CCC" Width="25" />
<ListBox Grid.Column="1" />
<GridSplitter Width="5" Grid.Column="2" Name="splitterB" HorizontalAlignment="Left" />
<Grid Background="Aqua" Grid.Column="2" Margin="5,0,0,0" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition />
<ColumnDefinition MinWidth="30"/>
</Grid.ColumnDefinitions>
<TextBlock Text="BBB" Width="25" />
<ListBox Grid.Column="1" />
<GridSplitter Width="5" Grid.Column="2" Name="splitterA" HorizontalAlignment="Left" />
<Grid Background="BurlyWood" Grid.Column="2" Margin="5,0,0,0" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Text="AAA" Width="25" />
<ListBox Grid.Column="1" />
</Grid>
</Grid>
</Grid>
Why does it work when I remove the listboxes?
Note: I modified the question and XAML code slightly to clarify things and also to show what I just found about the listboxes.
I've been playing around with the code for a little bit and it looks like your main problem lies in the fact that your GridSplitters don't have their own columns.
The way GridSplitter works is it adjusts the column immediately to the left and immediately to the right of it. So simply adding an additional column for a GridSplitter won't quite cut it, since you will then have 4 columns in your Grid, and you need both columns to the left of the splitter to be affected. So I would recommend putting those in an additional Grid.
The other problem is the MinWidth of 50 you have on the outer grid does not account for the width of the GridSplitter, so it should be 55.
It seems like this whole thing could be done more cleanly, but since I'm not sure exactly what you're trying to accomplish, I kept the "spirit" of your code intact and updated some things:
<Grid Background="CadetBlue">
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="50" Width="Auto"/>
<ColumnDefinition Width="3*"/>
<ColumnDefinition MinWidth="55" Width="5*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="CCC" />
<ListBox Grid.Column="0"/>
<GridSplitter Width="5" Grid.Column="1" />
<Grid Background="Aqua" Grid.Column="2">
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="25"/>
<ColumnDefinition Width="3*"/>
<ColumnDefinition MinWidth="25" Width="5*" />
</Grid.ColumnDefinitions>
<TextBlock Text="BBB"/>
<ListBox Margin="0,20,10,20"/>
<GridSplitter Width="5" Grid.Column="1" />
<Grid Background="BurlyWood" Grid.Column="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="AAA" Width="25" />
<ListBox Margin="0,20,10,20" Grid.Column="1" />
</Grid>
</Grid>
</Grid>
Hope this helps!
It's a WPF bug:
https://connect.microsoft.com/VisualStudio/feedback/details/636072/msdn-forum-grid-layout-issue-with-minwidth-starsizing
http://social.msdn.microsoft.com/Forums/en/wpf/thread/24460784-7d09-4627-89fe-975e0ca7b303
I got around it with a hack. If anyone has a better solution I'd love to hear it...
XAML:
<Grid Background="CadetBlue" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition />
<ColumnDefinition MinWidth="60"/>
</Grid.ColumnDefinitions>
<TextBlock Text="CCC" Width="25" />
<ListBox Grid.Column="1" />
<GridSplitter Width="5" Grid.Column="2" Name="splitterB" HorizontalAlignment="Left" DragDelta="splitterB_DragDelta" />
<Grid Background="Aqua" Grid.Column="2" Margin="5,0,0,0" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Name="bbbColumn"/>
<ColumnDefinition MinWidth="30"/>
</Grid.ColumnDefinitions>
<TextBlock Text="BBB" Width="25" />
<ListBox Grid.Column="1" Name="bbbListBox" />
<GridSplitter Width="5" Grid.Column="2" Name="splitterA" HorizontalAlignment="Left" DragDelta="splitterA_DragDelta" />
<Grid Background="BurlyWood" Grid.Column="2" Margin="5,0,0,0" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Text="AAA" Width="25" />
<ListBox Grid.Column="1" />
</Grid>
</Grid>
</Grid>
Code:
private void ToggleWidths()
{
if (bbbColumn.ActualWidth < 10
&& bbbListBox.Visibility != System.Windows.Visibility.Collapsed)
bbbListBox.Visibility = System.Windows.Visibility.Collapsed;
else if (bbbColumn.ActualWidth >= 10
&& bbbListBox.Visibility != System.Windows.Visibility.Visible)
bbbListBox.Visibility = System.Windows.Visibility.Visible;
}
private void splitterA_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
{
ToggleWidths();
}
private void splitterB_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
{
ToggleWidths();
}