Top align text inside TextBlock - wpf

Consider this XAML
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Text="Test" FontSize="80" Width="200" Height="100" Grid.Row="1" Background="DodgerBlue" Foreground="White" Text="Test"/>
</Grid>
It will show very clearly that there are a lot of spacing above the text. Is it possible to get rid of that space so that the capital T in "Test" starts at the top left corner of the textblock?
It does not have to be a textblock.
It cannot be solved using negative margins.
It cannot be solved by stretching the font.
If the text is moved inside the textblock, or the textblock itself is resized doesn't matter. I just need the solution to have no spacing above the highest letter in the text (here the capital T).

There are two nice solutions I have found some time ago on StackOverflow:
Add padding to the TextBlock.
Place TextBlock inside a border and let the border care about alignment.
Play around with them and you should get what you want.
edit: These are of course workarounds. There is no direct way to do vertical content alignment in a TextBlock that I know of.

Related

How do I bind the height of a StackPanel to the height of the containing Grid in WPF?

Im relatively new to WPF so I'm sorry in advance if there is a simple solution to this. However, I am trying to bind the height of a StackPanel to its containing Grid. I understand that a StackPanel automatically resizes to fit its elements but I would like to bind it to the Grid so that it does not do this. Right now the stack panel does not resize with the window since it remains the
size it needs to be in order to fit its elements.
Here is what I have so far:
<Grid x:Name="MainGrid" Grid.Row="2" Margin="1" Drop="Grid_Drop"
AllowDrop="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="175"/>
<ColumnDefinition Width="5"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel x:Name="SidePanel" Grid.Column="0" Height="{Binding
ActualHeight, ElementName=MainGrid, Mode=OneWay}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition/>
</Grid.RowDefinitions>
<local:DeviceTreeView x:Name="deviceTree" PyngInfo="{Binding
PyngSystemVm.PyngInfo}" Grid.Row="0"/>
</StackPanel>
<-- There is more code here but it is not important for answering this
question -->
</Grid>
I tried binding the height of "SidePanel" to the actual height of "MainGrid" but when I run this code and inspect the elements the Grid resizes with the window but the StackPanel does not. The StackPanel and the Grid even have different heights which doesn't make sense to me as their heights should be bound together.
I have also tried wrapping the entire StackPanel in a border and binding to that but that also did not work.
You don't need to bind the height of the StackPanel, simply setting its VerticalAlignment to Stretch will do it. However... You are still not going to get what I think you want. The StackPanel only stacks its child controls, it does not adjust them (at least not in the "stack" direction). Look into using a different control like Grid or UniformGrid or just expand your existing grid to have rows as well as columns.

ListBox in WPF page looks fine on my PC, but the data shrinks on smaller resolutions

I've tried almost every combination of alignments and margins, to no success. The ListBox is on a WPF page, which is bound to a frame on the main window.
The ListBox itself is fine. It aligns just as I expect it would. My ListBoxItem contains an Image and a TextBlock. The TextBlock gets cut off.
As you can see from the following image, things are mostly good.
The ListBox is appropriately offset from the left edge and the top of that blue box. The content Image and TextBlock are fairly centered and so is the ListBoxItem outline. This is on my development machine.
I thought the whole reason for using grids, grid lines, and alignment properties, was so we didn't have to set a hard coded size. That our controls would resize themselves. Which does actually work just fine for everything else.
But when I place this on a small screen, I get this:
The ListBox itself is still aligned correctly. But now the ListBoxItem is forced down. It's top alignment is still good, but the bottom is pushed down so we can't see the TextBlock or the bottom of the ListBoxItem.
Here's my XAML:
<Grid VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Margin="1">
<Grid.RowDefinitions>
<RowDefinition Height="292*" />
<RowDefinition Height="30*"/>
</Grid.RowDefinitions>
<ListBox Grid.Row="1" Name="lbButtons" Margin="2,0,0,1.5" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Visibility="Visible" >
<StackPanel Name="spListBoxItems" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Orientation="Horizontal">
<ListBoxItem Margin="0,0,0,0" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" >
<StackPanel Orientation="Vertical" HorizontalAlignment="Center" Margin="10,5,10,5">
<Image Source="/COBAN.CobanConsole.UI;component/Images/Buttons/Light/record48_light.png" />
<TextBlock Text="Record" Margin="5,5,0,0"></TextBlock>
</StackPanel>
</ListBoxItem>
</StackPanel>
</ListBox>
</Grid>
Not much to it. Any ideas on what's going on?
You're using * units on your grid row definitions. Those are relative measures: they just tell you what proportion of the space the rows can take up. If you need your listbox to have a specific height, you should change your second row to have an absolute size instead, like this:
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="30"/>
</Grid.RowDefinitions>

WP7: ScrollViewer viewport size

Windows Phone 7. I have a ScrollViewer inside a StackPanel inside a PivotItem inside a Pivot. Above the ScrollViewer, there are some other controls. My intention is that the ScrollViewer takes the available lower part of the screen (~400px), and its content is scrolled vertically (content height ~800px).
Now, right now there's no vertical scrolling - when I try to drag, the view returns in the previous position, as if the viewport size exactly matches the content size. When I look at the ViewportHeight property, it's ~800px - same as content.
Height of the ScrollViewer is not set ("Auto"); I was assuming it would take exactly the available space. That's obviously not the case. Question - short of setting Height by hand, is there a way to implement the logic of "viewport height is exactly how much vertical space you've got left"?
EDIT: here's the XAML, irrelevant details removed:
<Pivot x:Name="Root">
<ctls:PivotItem>
<ctls:PivotItem.Header>Title</ctls:PivotItem.Header>
<StackPanel>
<!-- More stuff here-->
<ScrollViewer Name="MenuPanel" HorizontalScrollBarVisibility="Disabled">
<Canvas x:Name="Menu" HorizontalAlignment="Left" VerticalAlignment="Top">
</Canvas>
</ScrollViewer>
</StackPanel>
</ctls:PivotItem>
</Pivot>
Width and height of the canvas are set in code.
Two things:
A StackPanel doesn't allow it's children to automatically take up the rest of the space available. Use a Grid, instead, with defined Rows. This allows your ScrollViewer to be in a container which is the exact height remaining vertically.
Your Canvas (inside the ScrollViewer) is aligned to top and left, and without a size defined, is exactly 0 pixels high and 0 pixels wide.
Good luck.
<Pivot x:Name="Root">
<ctls:PivotItem>
<ctls:PivotItem.Header>Title</ctls:PivotItem.Header>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<!-- More stuff here-->
</Grid>
<ScrollViewer
Grid.Row="1"
Name="MenuPanel">
<Canvas x:Name="Menu"
Height="500"
Width="500"/>
</ScrollViewer>
</StackPanel>
</ctls:PivotItem>
</Pivot>
Without seeing your XAML this is assummed - but based on commonly seen issues
The ScrollViewer is actually being assigned all the space it needs to include all it's content items.
Either give it an absolute height or wrap it in a Grid, which will limit it to the available space within the StackPanel.

Silverlight 4 - ScrollViewer and child DataGrid MinHeight

edit: I'm rewriting almost the entire question because I realized the question was incorrect and confusing. I apologize for this, but the question had incorrect assumptions that made it impossible to answer. I originally tried to simplify it to make it easier to understand, but this made it impossible to replicate my problem.
If I have an DataGrid with a MinHeight in a ScrollViewer, I would expect that as my ViewPort shrinks, the ActualHeight of the element would be decreased until it hits MinHeight before the scrollbars show up.
Instead, it seems that when the datagrid's rows cumulative heights add up to more than the MinHeight, this value overrides MinHeight
Is there a way to do this without manually sizing everything and having a ton of code?
Example:
<ScrollViewer VerticalScrollBarVisibility="Auto" Background="Red">
<Grid x:Name="LayoutRoot" Background="Black" HorizontalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition MinHeight="20"/>
<RowDefinition Height="80"/>
</Grid.RowDefinitions>
<sdk:DataGrid AutoGenerateColumns="True" Name="dataGrid1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" MinHeight="20" />
<Rectangle Fill="Blue" Width="100" Height="80" Grid.Row="1" />
</Grid>
</ScrollViewer>
If you were to populate this grid with some rows, if you maximize the window, the grid takes up most of the space and has white space after the rows. If you shrink it down, the layout takes away from the white space until that space runs out, then the root level ScrollViewer kicks in, even though MinHeight has not been reached.
If you replace the DataGrid with another rectangle, the behavior is different (obviously). The new rectangle would shrink down to height 20.
How do I achieve this with the grid? My requirements are to have nested scrollbars on my SL page (which I find distasteful, but it's not in my control). The idea is that the top level scrollbars are a "last resort" of sorts.
What about this:
<ScrollViewer>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="250" />
</Grid.RowDefinitions>
<Rectangle MinHeight="150" Background="Red" Grid.Row="0" />
<Rectangle Height="250" Background="Blue" Grid.Row="1" />
</Grid>
You did not have the Grid.Row values set on either of the rectangles.
You've not provided sufficient information to solve your specific problem. However, it is easy to demonstrate that the ScrollViewer does work in exactly the fashion you desire by distilling down to something as simple as:
<UserControl ...>
<ScrollViewer VerticalScrollBarVisibility="Auto">
<Border MinHeight="200" BorderBrush="Blue" BorderThickness="1" Background="Red"/>
</ScrollViewer>
</UserControl>
Put this in a standalone Silverlight application in the main page and you'll see that the ScrollViewer only displays the vertical scroll bar when the window is small enough. You can download the solution here.
This is because ScrollViewer itself has a border and padding that occupies little space of its own. Try considering little extra height that should match space of scrollbar border.
Another option will be to change the control template of scrollviewer and remove the border and extra space occupied around content presenter. And set horizontal scroll visibility to collapsed so it will not occupy space.

Why doesn't the contentpresenter fill the grid cell?

Ok I have a contentpresenter inside a grid cell:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<WrapPanel Grid.Row="0" Grid.Column="0">
<RadioButton GroupName="a" IsChecked="{Binding Path=SpecifyRatedValues, Mode=TwoWay}">Specify</RadioButton>
<RadioButton GroupName="b" IsChecked="{Binding Path=SpecifyRatedValues, Converter={StaticResource invertBoolean}}">Auto generate</RadioButton>
</WrapPanel>
<Border BorderBrush="Black" BorderThickness="3" Grid.Row="1" Grid.Column="0">
<ContentPresenter Content="{Binding Path=RatedValues}"></ContentPresenter>
</Border>
</Grid>
The contentpresenter finds which UI element to use by the datatemplate defined under resources:
<DataTemplate DataType="{x:Type ViewModels:RatedValuesViewModel}">
<Views:RatedValuesView />
</DataTemplate>
Now, everything works as expected, except for one thing: the View which is placed inside the contentpresenter at runtime does not expand to fill the entire cell. It leaves a big margin on the left and right side.
How can I make the view inside the contentpresenter fill the entire available area?
HorizontalAlign="Stretch" and VerticalAlign="Stretch" are important; however, you also have to remember how Grids work. Grid units are either in absolute pixels, "Auto", which means they size to fit their contents (i.e. minimum size to show everything), or "stars" which means fill up all available space.
Set your second RowDefinition's height to "*". You may also want to set easily-distinguishable border brushes and thicknesses on your grid. Sometimes, it's easy to think X isn't filling up all the available space, when it's really X's container, or X's container's container that isn't filling up the space. Use bright primary colors and large thicknesses (3 or so) and you can tell quickly who's not filling things up.
Chaiguy got it! The View had an explict Width and Height which constrained the view when placed in the cell. Thanks :-)
You must set HorizontalAlign=Stretch, VerticalAlign=Stretch to both Border and Content Presenter to fill the space in grid. and make width=auto.

Resources