VerticalAlignment="Stretch" stretches out of my container - wpf

I have a parent container that is used to hold all of my user controls. The issue is that I use VerticalAlignment="Stretch" to stretch contents to the full height and get a vertical scroll bar the user control gets stretched too much. The vertical scrollbar appears but there is no way to scroll. I know this because the down arrow for the scroll bar isn't visible.
I have <ContentControl Content="{Binding Workspace}" /> which is where a variety of controls can be assigned. For example, here is the XAML that is not working property in regards to stretching.
<StackPanel>
<TextBlock Text="{Binding FoundCount}" FontSize="13" Foreground="#666" Margin="0 0 0 8" />
<ScrollViewer VerticalAlignment="Stretch">
<TreeView
ItemsSource="{Binding Listing}"
Grid.Row="1"
BorderThickness="0"
VirtualizingStackPanel.IsVirtualizing="True" />
</ScrollViewer>
</StackPanel>
I only want to the TreeView to stretch and display a vertical scrollbar.
Any ideas?

I suspect the height of the StackPanel is not contrained so it grows to accomodate the ScrollViewer. You can check this by putting a border on the StackPanel.
<Border>
<StackPanel>
<TextBlock Text="{Binding FoundCount}" FontSize="13" Foreground="#666" />
<ScrollViewer VerticalAlignment="Stretch">
<TreeView ItemsSource="{Binding Listing}" BorderThickness="0"
VirtualizingStackPanel.IsVirtualizing="True" />
</ScrollViewer>
</StackPanel>
</Border>

Related

cannot display the slider of a scrollviewer

I can't get the slider for a scrollviewer to display. I have a listbox in a wrappanel. The listbox has a list of numbers. The list can be long enough to extend off of the bottom of the screen, so a scrollviewer is needed, but no matter how I set scrollviewer properties, or even if I put the listbox inside a scrollviewer inside the wrappanel, the slider doesn't appear. What am I doing wrong? Here's the XAML:
<WrapPanel Grid.Row="5" Grid.ColumnSpan="2">
<ListBox x:Name="lstBxCollisions"
HorizontalAlignment="Left" VerticalAlignment="Top"
Height="auto" Width="auto"
ItemsSource="{Binding MainWindow.lstBxCollisions}"
ScrollViewer.VerticalScrollBarVisibility="Auto"/>
<FlowDocumentReader Grid.Row="5" Grid.Column="1" Document="{Binding SingleAccidentFlowDocument}">
</FlowDocumentReader>
</WrapPanel>
Since your ListBox is inside WrapPanel, all its sizes are selected automatically and it begins to expand as the content size increases.
If you want it to appear ScrollBar, you need to fix the size of the ListBox by setting the actual height and width.
For example:
<WrapPanel Grid.Row="5" Grid.ColumnSpan="2">
<ListBox x:Name="lstBxCollisions"
HorizontalAlignment="Left" VerticalAlignment="Top"
Height="100" Width="100"
ItemsSource="{Binding MainWindow.lstBxCollisions}"
ScrollViewer.VerticalScrollBarVisibility="Auto"/>
<FlowDocumentReader Grid.Row="5" Grid.Column="1" Document="{Binding SingleAccidentFlowDocument}">
</FlowDocumentReader>
</WrapPanel>

How to make Buttons in ListBox all the same width

My WPF application contains a window that has a single ListBox in it. The View Model for the window contains an ObservableCollection of DomainViewModel objects.
The window defines the following DataTemplate:
<DataTemplate x:Key="DomainTemplate" DataType="DomainViewModel">
<Border BorderBrush="{Binding Converter={StaticResource BrushConverter}, Path=IsSelected}"
BorderThickness="2"
Name="SelectedBorder">
<Button Click="SelectDomain_Click"
Content="{Binding Path=Name}"
FontSize="16"
FontWeight="Bold"
Height="60"
HorizontalAlignment="Stretch" />
</Border>
</DataTemplate>
And here's the ListBox's declaration:
<ListBox FontSize="16"
FontWeight="Bold"
Grid.Row="2"
ItemsSource="{Binding Path=Domains}"
ItemTemplate="{StaticResource DomainTemplate}"
Name="DomainListBox" />
When the window renders, each button is exactly wide enough to display the text in its Content property. But that's not what I want. I want each button to be the width of the ListBox, which is going to vary with the width of the window itself.
How do I get the Buttons to keep their width set to the ListBox's width?
<ListBox HorizontalContentAlignment="Stretch"
.../>

Stretch items to fill canvas

I have a Dockpanel with items inside a Canvas. The Dockpanel and any other items (Grid etc) that I place inside the Canvas, only take up their minimum required space. How do I stretch these items to fill the entire Canvas?
<Canvas x:Name="InfoCanvas" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Margin="72,53,0,0">
<DockPanel VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Margin="0,0,0,0" x:Name="ReferenceInfo" Canvas.Left="0" Canvas.Top="0">
<TextBox x:Name="ReferenceAuthor" GotFocus="FieldEnter" LostFocus="FieldLeave" FontSize="16" FontFamily="Segoe UI Light" Text="Author" Foreground="Gray" Background="Transparent" DockPanel.Dock="Top" VerticalAlignment="Top" HorizontalAlignment="Stretch" BorderThickness="0" Margin="0,2,0,2"/>
<TextBox x:Name="ReferenceTitle" GotFocus="FieldEnter" LostFocus="FieldLeave" FontSize="16" FontFamily="Segoe UI Light" Text="Title" Foreground="Gray" Background="Transparent" DockPanel.Dock="Top" VerticalAlignment="Top" HorizontalAlignment="Stretch" BorderThickness="0" Margin="0,2,0,2"/>
<TextBox x:Name="ReferenceDate" GotFocus="FieldEnter" LostFocus="FieldLeave" FontSize="16" FontFamily="Segoe UI Light" Text="Date" Foreground="Gray" Background="Transparent" DockPanel.Dock="Top" VerticalAlignment="Top" HorizontalAlignment="Stretch" BorderThickness="0" Margin="0,2,0,2"/>
</DockPanel>
</Canvas>
Thank you!
The Canvas panel doesn't really support that.
It's very basic - it just allows you to position children absolutely by using Top, Bottom, Left and Right, and it always gives them just the space they need.
So usually you would use a Grid with just 1 column and 1 row instead.
You can however bind the width and height of the DockPanel to the width and height of the Canvas. That way the DockPanel will always fill the Canvas.
<DockPanel VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
Margin="0,0,0,0" x:Name="ReferenceInfo" Canvas.Left="0" Canvas.Top="0"
Width="{Binding ActualWidth, ElementName=InfoCanvas}"
Height="{Binding ActualHeight, ElementName=InfoCanvas}">
What you can do is:
<Grid>
<Canvas x:Name="InfoCanvas">
<!--Elements with canvas layout here-->
</Canvas>
<DockPanel x:Name="ReferenceInfo">
<!--Elements with dockpanel layout here-->
</DockPanel>
</Grid>
By wrapping both panels in a grid like this you can place elements that you cant to position relative to left, top etc in the canvas. Both the canvas and the dockpanel will fill available space. Note that the elements in the dockpanel will be rendered above the elements in the canvas when the dockpanel is defined after in xaml.
I'm assuming the code you posted is pseudo code, if not you should just remove the canvas.

XAML TextBlock: How to make TextBlock have variable height?

I have a ListBox that contains TextBlocks.
Sometimes the content of a TextBlock is too long and I want the height of this entry to double or triple as needed to accommodate the text.
I tried TextWrapping="Wrap" but it doesn't work. Every TextBlock is still just one line in height.
Is there an easy way to fix the problem in XAML? Thanks.
* Additional info: I tried to simplify the question but perhaps the complete scenario is better.
I have a listbox whose entries are displayed according to a template in code below.
Each entry has 2 pieces of info: a product price followed by product name.
I don't want to use the horizontal scrollbar in the listbox and want the product name to be displayed in 2 or more lines if necessary. The product name is the 2nd TextBlock.
Here's my XAML:
<ListBox Name="listBox1" ItemsSource="{Binding}" Margin="10" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock MinWidth="40" TextAlignment="Right" Text = "{Binding ProductPrice}" />
<TextBlock Text = "{Binding ProductName}" TextWrapping="Wrap" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Disable the listbox horizontal scrollViewer. This way the textBlock will be forced to wrap.
XAML:
<ListBox ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<TextBlock TextWrapping="Wrap"/>
</ListBox>
Example result:
Edit:
From the XAML you added I'm confident that the problem lays in the StackPanel.
Try replacing it with Grid for example:
<ListBox Name="listBox1" ItemsSource="{Binding}" Margin="10" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock MinWidth="40" TextAlignment="Right" Text = "{Binding ProductPrice}" />
<TextBlock Grid.Column="1" Text = "{Binding ProductName}" TextWrapping="Wrap" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
StackPanel doesn't limit the content size, therefore the textBlock doesn't knows where the space ends , and the wrapping doesn't happens.
You are using StackPanel. Try using DockPanel:
<DockPanel>
<TextBlock DockPanel.Dock="Left" MinWidth ="40" TextAlignment="Right" Text = "11.12" />
<TextBlock Text = "{Binding LongText}" DockPanel.Dock="Right" TextWrapping="Wrap" />
</DockPanel>
For Example:
this will help you do that. Dont Size the TextBlock just size the scroll viewer because texblock needs to be variable so ScrollViewer will apply Scrollbar once it goes beyond the size of ScrollViewer .
<ScrollViewer HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto">
<TextBlock/>
</ScrollViewer>
For ListBoxItem
<ListBox ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.Items>
<TextBlock Text="{Binding LongText}" TextWrapping="Wrap"/>
</ListBox.Items>
</ListBox>

Width of child control should match width of parent container

I'm pretty new to WPF. I often find my self struggling with getting a bunch of child controls combined width to match a given parent container.. As in the following:
<ListBox x:Name="BrugereListBox" Grid.Column="0" Grid.Row="3" DataContext="{DynamicResource Brugere}"
ItemsSource="{Binding}"
PreviewMouseLeftButtonDown="BrugereListBox_MouseLeftButtonDown"
PreviewMouseMove="BrugereListBox_PreviewMouseMove"
>
<ListBox.ItemTemplate >
<DataTemplate >
<Border BorderBrush="Black" BorderThickness="1" Margin="2">
<StackPanel Orientation="Vertical" IsEnabled="True"
PreviewMouseLeftButtonDown="StackPanel_PreviewMouseLeftButtonDown">
<StackPanel Orientation="Horizontal" >
<Label>Navn</Label>
<TextBox Text="{Binding Name}"></TextBox>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Label>Password</Label>
<TextBox Text="{Binding Password}"></TextBox>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Label>Email</Label>
<TextBox Text="{Binding Email}"></TextBox>
</StackPanel>
</StackPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
In this case I'm interested in getting the width of the children of the stackpanel:
<StackPanel Orientation="Horizontal" >
<Label>Navn</Label>
<TextBox Text="{Binding Name}"></TextBox>
</StackPanel>
to match the width of
<ListBox x:Name="BrugereListBox"
Any generic solution to scenarios like this?
turns out to be a dupe of:
wpf border control to span the width of listboxItem
and the answer given there:
This is probably more to do with the
ListBoxItems themselves not taking up
the full width of the ListBox. Add the
HorizontalContentAlignment="Stretch"
attribute to your ListBox and see if
it stretches the individual items to
fill the width.
so change to:
<ListBox x:Name="BrugereListBox" Grid.Column="0" Grid.Row="3" DataContext="{DynamicResource Brugere}"
ItemsSource="{Binding}"
PreviewMouseLeftButtonDown="BrugereListBox_MouseLeftButtonDown"
PreviewMouseMove="BrugereListBox_PreviewMouseMove"
HorizontalContentAlignment="Stretch"
>
but as Kent says, using a Grid would be better in my opinion.
Use the right panel and you'll be fine. StackPanel makes its own decisions about its width/height depending on its orientation and its children. Use a Grid and it will just take up the space it is given - no more, no less.

Resources