StackPanel in StatusBar won't stretch - wpf

When I add StackPanel to the StatusBar as last StatusBarItem it won't fill up all additional space. I wonder why is that since StatusBar internally uses DockPanel as ItemsPanel.
Here's a sample code:
<Window x:Class="Foo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Zadatak1"
Title="MainWindow"
WindowState="Maximized">
<DockPanel>
<StatusBar DockPanel.Dock="Bottom">
<StatusBarItem DockPanel.Dock="Left" Background="SkyBlue">
<Label>Status....</Label>
</StatusBarItem>
<StatusBarItem Background="Red" DockPanel.Dock="Right" HorizontalAlignment="Right">
<StackPanel Orientation="Horizontal">
<Label>Time:</Label>
<Label>02:48:AM</Label>
</StackPanel>
</StatusBarItem>
</StatusBar>
</DockPanel>
If I change the order of the elements so Label is first and StackPanel is second, it fills additional space as it should.

It is the red StatusBarItem that doesn't fill the space since you set its HorizontalAlignment property to Right. Change it to the default value of Stretch if you want it to fill the DockPanel.
The StackPanel does fill the StatusBarItem as expected.

Related

WPF - Stretch expander when having HorizontalAlignment set to Left on page

So i was wondering if its posible to stretch a expander on a page when having HorizontalAlignment set to left on a Usercontrol/page.
The problem is that we dont want to set a width on the expander because we want it to resize when resizing the application. We also cant set a minwidth on the expander because our application also has a minwidth of 850 and a normal width of 1200 and we want the expander always stretch to the maximum size.
Code sample:
<UserControl x:Class="WpfApp1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
d:DesignWidth="1100" HorizontalAlignment="Left">
<DockPanel>
<StackPanel>
<Expander Background="LightBlue"/>
</StackPanel>
</DockPanel>
</UserControl>
Our main goal is to create something like the image below where the radio button is always on the right and the expander sizes to it's avaible space.
If you are using DockPanel just use its Dock property for child elements and set LastChildFill="True" (Expander should be the last child element of course).
Something like this:
<DockPanel LastChildFill="True">
<RadioButton DockPanel.Dock="Right" Content="Active"/>
<Expander DockPanel.Dock="Left" Header="title1" Background="LightBlue"/>
</DockPanel>
Can you set the HorizontalAlignment to Stretch where you are using your control?
<Window ...>
<Grid>
<local:Window1 HorizontalAlignment="Stretch"></local:MainWindow>
</Grid>
</Window>
(Where local:Window1 is your user control as defined in the question)
We solved the isue by using a grid with column width set to auto and * in the expander header:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>

How to re-height border for windows resize in XAML WPF

I have a more StackPanels in my XAML. Every StackPanel has a border inside.
When I modify the Main Window the width follows the resizing. But the height follows only in one the bigger direction. If I make the Window smaller the height of the borders doesn't follows. So the effect is the Botton border line isn't visible. How can I do this ?
<Window x:Class="MyStackPanel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MyCombobox" Height="356" Width="475">
<Grid>
<StackPanel x:Name="STP"
Margin="10">
<Border x:Name="STPB"
BorderBrush="#FFE80707"
BorderThickness="5"
CornerRadius="10"
Height="{Binding ElementName=STP,Path=ActualHeight}"/>
</StackPanel>
</Grid>
</Window>
!border normaly Looks like
Use a Grid instead of a StackPanel then the border will stretch to the
Grids height and width on resizing
<Grid x:Name="STP"
Margin="10">
<Border x:Name="STPB"
BorderBrush="#FFE80707"
BorderThickness="5"
CornerRadius="10" />
</Grid>
Window after your changes, Looks like the same after reize (make smaller) without your changes.
http://i.stack.imgur.com/SplMn.jpg

TextBlock text wrapping pushes other components

I have a TextBlock and a couple Buttons in a StatusBar. The Buttons are effectively right-aligned (e: actually the StatusBarItem containing them is). When the window is shrunk horizontally, and the text wraps, the TextBlock pushes the Buttons off the window to varying degrees.
Why does this happen, and how can I fix the positions of the Buttons?
<Window x:Class="TextWrapping.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<DockPanel>
<StatusBar DockPanel.Dock="Bottom">
<StatusBarItem>
<TextBlock Name="statusText" TextWrapping="Wrap" Text="when this text wraps, it pushes the buttons off the window" />
</StatusBarItem>
<StatusBarItem HorizontalAlignment="Right">
<StackPanel Orientation="Horizontal">
<Button>one</Button>
<Button>two</Button>
</StackPanel>
</StatusBarItem>
</StatusBar>
<TextBlock Text="shink this window horizontally" />
</DockPanel>
</Window>
You can see this blog post for more information, but basically the StatusBar is using a DockPanel to present it's items. So for the code you have above, the statusText is being docked left, and the buttons are filling the remaining space (but aligned horizontally within that area).
So as you size smaller, the TextBlock will always take as much space as it needs (allowing the buttons to size to zero). When the text is wrappped, the buttons get back a little more space as the TextBlock doesn't need all the horizontal space.
To fix it you can change your code to:
<DockPanel>
<StatusBar DockPanel.Dock="Bottom">
<StatusBarItem DockPanel.Dock="Right">
<StackPanel Orientation="Horizontal">
<Button>one</Button>
<Button>two</Button>
</StackPanel>
</StatusBarItem>
<StatusBarItem>
<TextBlock Name="statusText" TextWrapping="Wrap" Text="when this text wraps, it pushes the buttons off the window" />
</StatusBarItem>
</StatusBar>
<TextBlock Text="shink this window horizontally" />
</DockPanel>
Or you can use the trick shown the blog post, to replace the DockPanel with a Grid.

TextBox expanding with surrounding Grid but not with text

A window has a Grid with two columns. The left column contains a control with a constant width but with a height that adapts. The right column contains a TextBox that takes up all remaining space in the Grid (and thereby in the Window).
The Grid is given a minimal width and height and is wrapped within a ScrollViewer. If the user resizes the window to be smaller than the minimal width/height of the Grid, scrollbars are displayed.
This is exactly how I want it to be. However, a problem occurs when the user starts typing text. If the text is to long to fit in one line in the TextBox, I want the text to wrap. Therefore I set TextWrapping="Wrap" on the TextBox. But since the TextBox has an automatic width and is wrapped in a ScrollViewer (its actually the whole Grid that is wrapped), the TextBox just keeps expanding to the right.
I do want the TextBox to expand if the window is expanded, but I don't want the TextBox to expand by the text. Rather the text should wrap inside the available TextBox. If the text don't fit within the TextBox height, a scrollbar should be displayed within the TextBox.
Is there a way to accomplish this?
Below is some code that shows my problem:
<Window x:Class="AdaptingTextBoxes.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="300" Width="400" Background="DarkCyan">
<Grid Margin="10" Name="LayoutRoot">
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Grid MinWidth="300" MinHeight="200">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Grid.Column="0" Margin="0,0,10,0" Content="Button" Width="100" />
<TextBox Grid.Column="1" AcceptsReturn="True" TextWrapping="Wrap" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Auto" />
</Grid>
</ScrollViewer>
</Grid>
</Window>
You could use an invisible border (its hacky but it works - its how I tend to sort out dynamic textbox sizes in Xaml):
<Border BorderThickness="0" x:Name="border" Grid.Column="1" Margin="0.5" />
<TextBox Grid.Column="1" AcceptsReturn="True" TextWrapping="Wrap" Width="{Binding ActualWidth, ElementName=border}" Height="{Binding ActualHeight, ElementName=border}" />
Have you tried setting the MaxWidth property on just the TextBox?
Edit after OP's comment
I would try getting rid of the ScrollViewer. The sizing used in the Grid's layout should take care of re-sizing and the scroll bar settings on the TextBox should take care of the rest.
The answer is based on Leom's answer.
The solution works great when you enlarge the window, but the resizing is not smooth when you make the window smaller. As the textbox participates in the grid's layout, it has to perform layout process multiple times. You can fix that by putting the texbox in the canvas, so the change of the size of the textbox no longer triggers the grid's re-layout.
The updated code:
<Border BorderThickness="0" x:Name="border" Grid.Column="1" Margin="0.5" />
<Canvas Grid.Column="1">
<TextBox AcceptsReturn="True" TextWrapping="Wrap" Width="{Binding ActualWidth, ElementName=border}" Height="{Binding ActualHeight, ElementName=border}" />
</Canvas>

How to incorporate Canvas into a larger layout in WPF?

Canvas doesn't seem to play well together nicely with the other elements when you try to build it into a layout and have e.g. controls on the side and the canvas is the drawing area.
For instance, why can I put a border around every element except a canvas? In the following code, border wraps canvas but the canvas only has the border on the top but not on the left, right or bottom:
<Window x:Class="WpfApplication25.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<StackPanel>
<TextBlock DockPanel.Dock="Bottom" Text="Move the slider to reveal the answer:"/>
<Slider DockPanel.Dock="Bottom" Name="theSlider"
HorizontalAlignment="Left"
Width="200"
Minimum="0"
Maximum="1"
Value="1"
Cursor="Hand"/>
<Border BorderBrush="Tan" BorderThickness="2">
<Canvas>
<TextBlock Canvas.Left="45" Canvas.Top="50" Text="test" FontSize="16"/>
<Rectangle
Canvas.Left="10"
Canvas.Top="10"
Width="100"
Height="100"
Fill="Silver"
Opacity="{Binding ElementName=theSlider, Path=Value}"
/>
</Canvas>
</Border>
</StackPanel>
</Window>
From what I can tell in XamlPad, the problem appears to be that your Canvas does not have an explicit height/width, and that its HorizontalAlignment defaults to being in the middle of the Border. Without an explicit height and width the Border appears to collapse to 0 height and stretches on the width. My assumption is this is because your Border is in a StackPanel, as placing the Border in a Grid, causes it to behave as expected.
Your best bet is to give the Canvas an explicit Height and Width. Not sure that is what you're looking for though.
As far as I understand what you are trying to achieve, you should place your controls in one cell of a Grid and your Canvas in another.

Resources