WPF: Aligning the base line of a Label and its TextBox - wpf

Let's say I have a simple TextBox next to a Label:
<StackPanel>
<StackPanel Orientation="Horizontal">
<Label Margin="3">MyLabel</Label>
<TextBox Margin="3" Width="100">MyText</TextBox>
</StackPanel>
...
</StackPanel>
This yields the following result:
As you can see, the base lines of MyLabel and MyText are not aligned, which looks ugly. Of course, I could start playing around with the margins until they match up, but since this is such a common requirement I'm sure that WPF provides a much easier and more elegant solution, which I just haven't found yet...

This behaviour is, I think, caused by the fact that the TextBox defaults to a vertical alignment of Stretch, which causes it to fill the available space and have the extra couple of pixels under the text. If you use this instead:
<StackPanel>
<StackPanel Orientation="Horizontal">
<Label >MyLabel</Label>
<TextBox VerticalAlignment="Center" Width="100">MyText</TextBox>
</StackPanel>
</StackPanel>
... you should see a cleaner result.

What do you think?
<StackPanel Orientation="Horizontal">
<Label Margin="3" VerticalContentAlignment="Center">MyLabel</Label>
<TextBox Margin="3" VerticalContentAlignment="Center" Width="100">MyText</TextBox>
</StackPanel>

I achieved that look in Kaxaml with:
<StackPanel Orientation="Horizontal">
<Label Margin="3" VerticalAlignment="Center">MyLabel</Label>
<TextBox Margin="3" Width="100" VerticalAlignment="Center">MyText</TextBox>
</StackPanel>

I know that this is an old answer, but for here's an example for those who seek another way, where you don't need to rely on a fixed textbox width:
Instead of StackPanel, use a DockPanel and .Dock.
This proves to be very handy when used inside a Grid.
<DockPanel Grid.Column="2" Grid.Row="2">
<Label Content="SomeTitle:" DockPanel.Dock="Left"></Label>
<TextBox x:Name="SomeValueTextBox" VerticalAlignment="Center" DockPanel.Dock="Right"></TextBox>
</DockPanel>

This question is not as trivial as it looks and the accepted answers lacks details. If you try custom heights with the controls, you will see issues.
First, this is the correct implementation as answered by User7116.
<StackPanel Orientation="Horizontal">
<Label Margin="3" VerticalAlignment="Center">MyLabel</Label>
<TextBox Margin="3" Width="100" VerticalAlignment="Center">MyText</TextBox>
</StackPanel>
The tricky part is that there two level of vertical alignments here so understand how the alignments works.
When we specify alignment for a control, we are telling it how to position itself in the parent container (See documentation). So when we specify VerticalAlignment="Center"> to the TextBox we are telling it that this TextBox should appear vertically centered in parent stackpanel.
Now the actual text inside that TextBox could also use vertical alignment within that TextBox! This is the 2nd level and actually quite tricky and is answered here.
If you experiment with setting the Label's height above to say 50 as well, you will see they will not align again. This is because Label is now taking larger area and its text inside that area is not vertical aligned so it doesn't look aligned again.
The code for above is:
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<Label Margin="3" VerticalAlignment="Center" Height="50">MyLabel</Label>
<TextBox Margin="3" VerticalAlignment="Center" Width="50" Height="50">MyText</TextBox>
</StackPanel>
Luckily when control height is default (like label control), it's just tall enough to contain the text so the inside alignment doesn't matter. But it comes into play if someone is setting custom heights for these controls and its better to understand how this works.

Related

Cannot align label in stackpanel

I'm not a wpf expert, so maybe the problem is really simple than appear. Anyway, I made a stackpanel with this structure:
<StackPanel Orientation="Horizontal">
<Label Content="Match" FontWeight="Bold"/>
<Label Content="Foo" HorizontalAlignment="Right"/>
</StackPanel>
How you can see I set the orientation to horizontal so I can have both label in the same row. I need also to align the second label "Foo" to right. I tried setting the HorizontalAlignment property, but, the label is stuck on the same position. What I can do for fix this?
The simplest answer is that you can't.
Stackpanel is made to stack things after each other.
You can do it either vertically of horizontally and you can align the stackpanel to the right or left but you cannot align the items inside it.
You can use Grid or another container instead.
<Grid>
<Label Content="Match" FontWeight="Bold" HorizontalAlignment="Left"/>
<Label Content="Foo" HorizontalAlignment="Right"/>
</Grid>
StackPanel does not support the individual alignment of the child controls. However you can set the alignment of the whole stackpanel. However its not the case here.
What you can do is put your labels in a Uniform Grid of 1 row and 2 columns.
<UniformGrid Rows="1" Columns="2">
<Label Content="Match" FontWeight="Bold"/>
<Label Content="Foo" HorizontalAlignment="Right"/>
</UniformGrid>

How to use Textwrap property without defining the width in windows phone development?

I am using a grid with single row. I have placed a single LongListSelector within that row. The ItemTemplate is as follows,
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<!--when we dont mention any of the height and width properties then control tries to first occupy the minimum height/width required and then it streches to the extent it is possible-->
<phone:LongListSelector Grid.Row="0" x:Name="CLASS1">
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="25,20" Background="#FF616464" Width="Auto">
<TextBlock Text="{Binding title, Mode=TwoWay}" FontSize="40" Margin="20,20" Foreground="White" TextAlignment="Left" TextWrapping="Wrap" FontStyle="Normal" FontFamily="Segoe UI"/>
</StackPanel>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>
</Grid>
Now I know that if we don't mention the width,MaxWidth values in the XAML file or in the properties, the Textblock above will stretch itself to the width it really needs to fit in the text. If there still some more width remaining it will expand till that extent. However I want to wrap the text of the Textblock. At the same time I want to utilize all the width available for stretching the TextBlock. So basically I want that the Textblock to stretch itself using the maximum width available and if the Text within it is still longer then I want to wrap it. Is there any solution to achieve this. I can use text wrap by setting constant value for width. As I want to deploy this application on different models then can I make it generic? Is there anyway to use parent's width?
All you have to do is to replace StackPanel with Grid.
<DataTemplate>
<Grid Margin="25,20" Background="#FF616464" Width="Auto">
<TextBlock Text="{Binding title, Mode=TwoWay}" FontSize="40" Margin="20,20" Foreground="White" TextAlignment="Left" TextWrapping="Wrap" FontStyle="Normal" FontFamily="Segoe UI"/>
</Grid>
</DataTemplate>
Result:
try this property
HorizontalContentAlignment="Stretch"

My rowSpan doesn't take 2 lines

I got a weird problem with the rowSpan property of a grid.
I got a text that will take more than one line, so I told his stack spanel, RowSpan="2", so the text can be on multiple line, using Wrapping to, like this :
<StackPanel Grid.Row="0"
Grid.RowSpan="2"
Orientation="Horizontal">
<TextBlock x:Name="tbConfirm"
Text={Binding TextConfirm}
HorizontalAlignment="Center"
TextWrapping="Wrap"
VerticalAlignment="Center"
Grid.RowSpan="2"
FontSize="12">
</TextBlock>
</StackPanel>
The property TextConfirm contains a text that should take two lines (I tried with the text without binding to see if it fills.
But, despite my RowSpan and my TextWrapping, it still on one line, and don't understand why.
When I make a column span, it will take the number of column define, but why row span doesn't work?
There is in the Grid, 5 column(width auto) and 5 row(height auto) define.
If I want to have one textblock, one textbox, and another one textblock.
How can I tell to go in the new line automatically?
Undefined width for the two textblocks, and define width for the textbox.
This is just an example, I don't wrote it at the moment.
<StackPanel Grid.Row="0"
Grid.RowSpan="2"
Orientation="Horizontal">
<TextBlock x:Name="tbConfirm"
Text={Binding TextConfirm}
HorizontalAlignment="Center"
TextWrapping="Wrap"
VerticalAlignment="Center"
Grid.RowSpan="2"
FontSize="12">
</TextBlock>
<textBox width ="200"/>
<TextBlock x:Name="tbConfirm2"
Text={Binding TextConfirm2}
HorizontalAlignment="Center"
TextWrapping="Wrap"
VerticalAlignment="Center"
Grid.RowSpan="2"
FontSize="12">
</TextBlock>
</StackPanel>
Will this, go automatically at the new line if necessary? Or do I need to define lines and colums in the xaml?
Thank you.
I'm not sure if i understand the question correctly but to get the text wrapping you don't need to span accross multiple rows. From what i've read you have set the column width to auto so it will let the TextBlock "grow" freely. If you want to get the wrapping working you should define a fixed width either on the column or on the TextBlock itself (and keep the TextWrapping="Wrap").
try binding the width of the textblock to that of the parent as you wont want it to exceed that
<TextBlock x:Name="tbConfirm"
Text="asasddadsa adassdasd asdasdasdsa asdasdssd asdasdasjdahsjakdhksajdhjsaalskasj skjdsajkdhajhasaskjhdsahsakdasjdhsajdhasjdhkjsad"
HorizontalAlignment="Center"
Foreground="Black"
Width="{Binding ActualWidth, ElementName=stackPanelParent}"
TextWrapping="Wrap"
VerticalAlignment="Center"
FontSize="12">
</TextBlock>
I gave my own content to test. In case it overflows let me know.

Binding to DevExpress GridControl TotalSummary

I have a basic newbie binding question, which isn't necessarily directly related to the control used. Anyway, here's the thing: I have a DXGrid with a TotalSummary defined, which counts the rows of the grid.
<dxg:GridControl.TotalSummary>
<dxg:GridSummaryItem x:Name="grdCompleteCount" FieldName="ar_id" SummaryType="Count"/>
</dxg:GridControl.TotalSummary>
Now I'd like to display the count not at the bottom of the grid as it is done automatically, but would like to bind it to another element, say, a textblock. Something like this:
<TextBlock x:Name="statusBarGridCount"
Text="{Binding ElementName=grdCompleteCount, Path=Value}"
TextAlignment="Right"
Width="190" />
But this approach doesn't work as I'm not sure how to get to the value I'm looking for. What's wrong with the binding?
Ok, got it already, don't worry... :) Works that way:
<StatusBarItem Grid.Column="2" BorderThickness="1" Margin="1">
<TextBlock x:Name="statusBarGridCount"
Text="{Binding ElementName=grdList, Path=VisibleRowCount}"
TextAlignment="Right"
/>
</StatusBarItem>

WPF: Is there a sort of XAML tag that behaves like the HTML span element?

Coming from ASP.NET, this WPF stuff is just confusing. All I want to do is put a red asterisk by a label to indicate a required field. Playing around with stuff, I found that this actually does the trick:
<TextBlock Grid.Row="6" Height="28" HorizontalAlignment="Left" VerticalAlignment="Top">
<Label Foreground="Red" Content="*" /><Label Content="Heavy Weight" />
</TextBlock>
Being that I just came up with this, I am not convinced it's the academic route a seasoned WPF developer would take. Additionally, this markup puts a huge amount of white space in between the asterisk and the label. In HTML, a span element would just render right beside its next sibling element. FYI, I tried putting a label within a label, but VS2010 kept barking about "The property 'content' is set more than once".
Any ideas?
Something like this would be more appropriate:
<TextBlock Grid.Row="6" Height="28" HorizontalAlignment="Left" VerticalAlignment="Top">
<Span Foreground="Red">*</Span>Heavy Weight
</TextBlock>
Here is an overview of what can go into a TextBlock's content, more specifically here.
one more way is
<TextBlock Grid.Row="6" Height="28" HorizontalAlignment="Left" VerticalAlignment="Top">
<Run Foreground="Red" Text="*" />
<Run Text="Heavy Weight" />
</TextBlock>
btw
Damascus's solution adds more UI Elements.
with CodeNaked's solution, its difficult to databind the Text.
The explanation is that you actually put two elements one after the other. You need to put them into a container.
Just a sample code of a sentence with red asterisk I did recently:
<StackPanel Orientation="Horizontal" Margin="5" >
<TextBlock Text="Display name"/>
<TextBlock Text="*" Foreground="Red" FontWeight="Bold" />
<TextBlock Text=":"/>
</StackPanel>
There, everything is in a StackPanel, so property 'content' will actually be set once (if you don't specify a group panel such as this one, you'll have to add only one element)

Resources