How to prevent TextBox from stretching vertically inside Grid - wpf

In the markup below, the text box vertically to fills the entire grid row, no matter how big the row's height is. For a single line text box this does not look good. I need it to center vertically instead and have the height just enough to fit the current font. Setting the Height property on the text box helps but I do not want to hard code the height in case the font changes.
<Grid FocusManager.FocusedElement="{Binding ElementName=TitleBox}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBox Name="TitleBox"
Text="{Binding Title, UpdateSourceTrigger=PropertyChanged}"
Grid.Column="0" />
<Button Command="{Binding CreateCommand}"
IsDefault="True"
Grid.Column="1">Create</Button>
</Grid>

Set the VerticalAlignment of the text box to Center. The default is Stretch which explains why it stretches to fill the entire grid cell:
VerticalAlignment="Center"

Related

Limit width of TextBox to the width of the ListView that contains it

I am working on a MVVM app (the examples here are not very MVVM though, its just a mockup).
I have a ListView, that binds to a collection of TextItemViewModel instances, the view for these are defined in TextItemView. Each TextItemView contains a Grid with one Auto column and on * column to fill. The fill column contains a TextBox where the user can enter text.
I want the TextItemViews to fill the horizontal space of the ListView (this works), like so:
However, when a user enters long text in a box, I want it to expand in Height but not in Width. At the moment, the Width increases and the ListView gets a scrollbar, like so:
My ListView code looks like this: (I've taken out the MVVM Binding code and set the ItemsSource in the code-behind for this example)
<ListView Name="listview"
SelectionMode="Single"
Margin="5"
MinHeight="50"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch" />
And my TextItemView code looks like this:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Button Content="SomeButton"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Margin="5"
Grid.Column="0" />
<TextBox Text="{Binding Path=NoteText}"
TextWrapping="Wrap"
AcceptsReturn="True"
AcceptsTab="True"
VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Disabled"
HorizontalAlignment="Stretch"
Margin="5"
Grid.Column="1" />
</Grid>
Can anyone advise me on how to force the TextItemView to fill the width of the ListView (as it does), but to then wrap the TextBox and expand TextItemView in Height when the TextBox fills up?
OK I got this now thanks to WPF - How to stop TextBox from autosizing?
Trick is to add the following to ListView definition:
ScrollViewer.HorizontalScrollBarVisibility="Disabled"

WPF ListView TextBlock TextWrapping

I am building a ListView that needs to have five columns - the first one needs to have text that can be any length and needs to wrap whenever the window size changes (in addition to changing the row height so the wrapped text is visible) and the other four columns are a static width of 45. I've been searching for hours on this and every solution I come across either requires a static width or doesn't work.
Solutions tried:
Column widths of auto, 1*, 2*, etc. (settings ignored)
DockPanel (settings ignored)
WrapPanel (ignored)
Setting Width to RelativeSource of parent for ActualWidth (ignored)
Any ideas? It seems like a significant number of people have had this same problem, but I would highly prefer to not have to go the static width route for this column. Especially since the content just gets cut off when I do that anyway (even with height="Auto" for the row). The width of the overall window could be as small as 1024, but could also be 1600+ which is why I want dynamic sizing. That way smaller screens will have the content wrap and larger screens will just show the one line since the content fits.
Here is the XAML:
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="45" />
<ColumnDefinition Width="45" />
<ColumnDefinition Width="45" />
<ColumnDefinition Width="45" />
</Grid.ColumnDefinitions>
<!-- This is the TextBlock that needs to wrap its content (and
change the height of the row (so the full content is still
visible) to whatever the available space is, but should not
make overall ListView wider than the parent's width. -->
<TextBlock Text="{Binding Content}" Padding="20,6,6,6" />
<!-- These four blocks will have other content eventually, but only need
to be 45 wide -->
<TextBlock Text="X" Grid.Column="1" HorizontalAlignment="Center" />
<TextBlock Text="X" Grid.Column="2" HorizontalAlignment="Center" />
<TextBlock Text="X" Grid.Column="3" HorizontalAlignment="Center" />
<TextBlock Text="X" Grid.Column="4" HorizontalAlignment="Center" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
Not so easy...but it can be done.
I wrote a solution for you. In short, use Expression Blend to create a copy of the ListView Template and delete the ScrollViewer surrounding the ItemPresenter.
Here is a more indepth explanation:
How to have the TextBlock in a left column of a Grid in a ListView Template expand or shrink with text wrapping?
<ListView HorizontalContentAlignment="Stretch" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListView.ItemTemplate>
...
</ListView.ItemTemplate>
</ListView>
I'd add TextWrapping="Wrap" to the first TextBlock element.

Give a WPF Grid the width of a ScrollViewer minus the scrollbar

I have a WPF UserControl with two Grids above each other. The bottom Grid is in a ScrollViewer. The idea is to have the first Grid be the header of the second Grid. I'm having trouble with the width of the columns however. Both Grids should take up all the space they can (the width of the Window), but the top Grid should of course be a little less wide, because there's a scrollbar on the right of the bottom Grid.
This is the simplified Xaml I've got:
<UserControl>
<DockPanel>
<Grid DockPanel.Dock="Top">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
</Grid>
<ScrollViewer>
<Grid>
<Grid.ColumnDefintions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefintions>
</Grid>
</ScrollViewer>
</DockPanel>
</UserControl>
This renders fine actually, except that the most right column of the top Grid extends over the scrollbar, which I want to avoid.!
Here is an image of the result: Grid column and width of scrollbar. The red indicates where the column/cell is now, but I want it to stop at the blue line. I've tried SharedSizeGroups, but that seems to make my Grids small again (not take up the full space of the window).
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" Name="sv">
<Grid MinWidth="{Binding ElementName=sv, Path=ViewportWidth}" MinHeight="{Binding ElementName=sv, Path=ViewportHeight}" />
</ScrollViewer>
The problem is setting up a correct dependency between the ScrollViewer container size and the grid size. Let us consider just the width: the binding above allows the ScrollViewer to expose the horizontal scrollbar only if necessary:
enlarging a single column of the grid (eg. with a splitter) does not provoke the resizing of the other columns (which would happen if you bind Width instead MinWidth).
Using the ViewportWidth instead of ActualWidth takes into account the scrollbar width, if there is one.
Just try
Found the solution here. I gave my top Grid a Width:
Width="{Binding ElementName=BottomGrid, Path=ActualWidth}"

Silverlight: Set MaxWidth of a textblock to containing column width

in my Silverlight 4 App, I have a simple 3-columns Grid, that contains 3 Textblocks.
<Grid Background="{StaticResource BrushCharacteristicListBoxItemBackground}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.5*"/>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="0.5*"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="TextBlockCharacteristicName" Text="{Binding Property1}" HorizontalAlignment="Left" TextTrimming="WordEllipsis" ToolTipService.ToolTip="{Binding Text}" Margin="6,0,0,0" />
<TextBlock x:Name="TextBlockSeperator" Text="=" Grid.Column="1" />
<TextBlock x:Name="TextBlockCharacteristicValue" Text="{Binding Property3}" Grid.Column="2" HorizontalAlignment="Right" Margin="0,0,6,0" />
</Grid>
The width of the Grid depends on the containing user control. Now I want to cap the size of the first and the third textblock to the current size of their containing column, probably using MaxSize and bind it somehow to the size of the Column of the Grid.
Can anyone here tell me how to do this?
Thanks in advance,
Frank
By default the HorizontalAlignment property of the TextBlock is set to "Stretch" so it will fill the available size of the column its in, regardless of its content. Is that what you want?
Perhaps for some reason you do not want the TextBlock to be as wide as the Column it is in if its content does not need all the available space?
If so set the TextBlock.HorizontalAlignment to "Left". The TextBlock will then be only as wide as it needs to be until it reaches the width of the column, then its width will be constrained by the column.

WPF Listbox wont scroll Vertical

Within a Groupbox I have a Listbox, ListboxItems are defined in the XAML as well. The Listbox is defined:
<ListBox Name="lvAvoidCountry" Margin="5,5,5,5"
Background="Transparent"
ScrollViewer.VerticalScrollBarVisibility="Visible"
ScrollViewer.HorizontalScrollBarVisibility="Disabled" >
Items are defined like this:
<ListViewItem >
<CheckBox Name="chkAlbanien" Tag="55">
<StackPanel Orientation="Horizontal">
<Image Source="images/flag_albania.png" Height="30"></Image>
<TextBlock Text="Albanien" Margin="5,0,0,0"></TextBlock>
</StackPanel>
</CheckBox>
</ListViewItem>
If I remove the Scrollviewer Settings I get horizontal scrolling and the Items are well formatted - correct width. If I use the scrollviewer settings the items get cut off so that all items are placed on the listbox. (eg. the flag is shown, the checkbox is shown but the text is just "Alba").
Thanks for any hints!
As the name implies, ScrollViewer.HorizontalScrollBarVisibility="Disabled" disables horizontal scrolling. If you do that, but your ListBoxItems are too long, they'll get cut off. The StackPanel won't grow or shrink to fit into the ListBox, and it won't "wrap" your items to fit into the ListBox if it's too narrow, even if you add TextWrapping to the TextBlock. It's very stubborn. I think your main problem is that StackPanel.
Instead of a StackPanel, try using a Grid with 2 columns defined like so:
<ListViewItem >
<CheckBox Name="chkAlbanien" Tag="55">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Source="images/flag_albania.png" Height="30"/>
<TextBlock Grid.Column="1"
TextWrapping="Wrap"
Text="Albanien" Margin="5,0,0,0"/>
</Grid>
</CheckBox>
</ListViewItem>
Auto will "shrinkwrap" the image columns, and * will give the text all remaining space. Then add TextWrapping to your textblock in case it's still too long.
Edited: added more complete code example and changed my answer slightly.
if you want vertical scrolling in a listbox then don't put it in a stackpanel,instead use a grid.

Resources