WPF StackPanel - how to push items off bottom - wpf

I have a StackPanel spanning the entire screen vertically in a grid, and the panel's VerticalAlignment option set to Bottom. When I add items to the panel in code, their positions start at the bottom, and move up when I add more. This is desired. However, what is not desired is that after the screen is filled vertically with items, adding more pushes them off the top of the screen. My desire is to have additional items fall off the bottom; I don't care if they are not visible; I just don't want the topmost items to disappear.
Any tricks you might know of to help me through this? Thank you in advance.

My desire is to have additional items fall off the bottom
You need to wrap the StackPanel in another container that allows the StackPanel itself to grow as much as it wants, in a way that makes the StackPanel appear to expand from the bottom, but in reality expand from the top so that when it exceeds available space, the excess is removed from the bottom instead of the top.
The Grid control will do exactly that. For example:
<Window x:Class="TestSO67169225StackPanelFromBottom.MainWindow"
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"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<Style TargetType="TextBlock">
<Setter Property="FontSize" Value="36"/>
</Style>
</Window.Resources>
<Grid VerticalAlignment="Bottom">
<StackPanel>
<TextBlock Text="StackPanel Item 1"/>
<TextBlock Text="StackPanel Item 2"/>
<TextBlock Text="StackPanel Item 3"/>
<TextBlock Text="StackPanel Item 4"/>
<TextBlock Text="StackPanel Item 5"/>
<TextBlock Text="StackPanel Item 6"/>
</StackPanel>
</Grid>
</Window>
Looks like this:
But when you add more items, looks like this:

Related

Background drawing with inner offset

I want my UserControl to have black background. The little thing is that I want it to have some offset from the sides.
I did it like this:
<UserControl x:Class="PitramVisionPlayerUI.Controls.Readout"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="50" d:DesignWidth="200">
<UserControl.Background>
<DrawingBrush Stretch="Fill">
<DrawingBrush.Drawing>
<GeometryDrawing>
<GeometryDrawing.Geometry>
<PathGeometry>
<PathFigure IsClosed="True" StartPoint="0.1,0.1">
<PathFigure.Segments>
<LineSegment Point="0.9,0.1" />
<LineSegment Point="0.9,0.9" />
<LineSegment Point="0.1,0.9" />
</PathFigure.Segments>
</PathFigure>
</PathGeometry>
</GeometryDrawing.Geometry>
<GeometryDrawing.Brush>
<SolidColorBrush Color="Black"></SolidColorBrush>
</GeometryDrawing.Brush>
</GeometryDrawing>
</DrawingBrush.Drawing>
</DrawingBrush>
</UserControl.Background>
</UserControl>
Problem is that it does not work. It keeps filling the whole rectangle. If I replace DrawingBrush's property Stretch from "Fill" to "None" I am getting a black dot right in the middle of my UserControl.
Without a precise description of how exactly you want your control to behave, it's impossible to provide precise details as to exactly what your code should look like.
As a general rule, for a DrawingBrush (or any TileBrush for that matter), you can use the Viewbox and Viewport properties to modify how the basic content of the brush is rendered. For example, by providing a viewbox that is a little larger than the actual content, it is possible to shrink the overall rendering within the viewport (i.e. the output area).
But, it's been my experience that the viewbox/viewport approach is always a bit "fiddly". Or rather, it's hard to gain a good intuitive grasp of what those parameters do, and so one often winds up just fiddling with the values until they get the results they want, with the result that the implementation is not very well generalized or reusable.
From your question, it's unclear what your desired relationship between this inset black background and the rest of the content in the control would be. However, one very straightforward approach would be simply to set the Padding property of the UserControl itself, thus causing all of the content inside the control to be inset by the given padding amount.
For example:
<UserControl x:Class="TestSO58234176BackgroundBorder.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:l="clr-namespace:TestSO58234176BackgroundBorder"
<!-- Padding set to 5 pixels, so content (including background) is inset -->
Padding="5" mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid Background="Black">
<!-- Stretch the text so it's clear what the extent of the content is -->
<Viewbox Stretch="Fill">
<TextBlock Text="This is a test" Foreground="LightGreen" FontWeight="Bold"/>
</Viewbox>
</Grid>
</UserControl>
This will do exactly that. I.e. all of the content, including any background it has, will be inset within the user control by 5 pixels. It looks like this:
(The red border is in the window's markup, around the user control, so it's easier to see the actual dimension of the user control itself.)
On the other hand, maybe you want for the content to fill the control completely, but have just the background inset. While (as I mentioned) you can fiddle with the background brush's viewbox and viewport for complete control of the rendering of the background, and in theory this might even be the "best" or "most correct" way to do it, in most cases it should not be necessary. Instead, just provide separate element providing the background and which is displayed under the rest of the content of the control.
<UserControl x:Class="TestSO58234176BackgroundBorder.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:l="clr-namespace:TestSO58234176BackgroundBorder"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<!-- Put a black rectangle under the actual content of the control, to act as an inset background -->
<Rectangle Fill="Black" Margin="5"/>
<!-- Put the actual content of the control inside this <ContentControl/> element -->
<ContentControl>
<Viewbox Stretch="Fill">
<TextBlock Text="This is a test" Foreground="LightGreen" FontWeight="Bold"/>
</Viewbox>
</ContentControl>
</Grid>
</UserControl>
That would look like this:
While the above example uses a <ContentControl/> element to contain the actual content of the user control, this isn't strictly necessary. It's just a convenient way to represent "here's where all your content goes". But of course, any sort of content can go here, as long as it's a valid child of a <Grid/>. The key here is that it shares the grid cell with the inset <Rectangle/> element that is acting as the background, and so renders as overlaid on top of that background.
If you like, you can even generalize the above, so that the "background" rectangle is part of the user control's template, instead of direct content. This way, there's a clear separation between what's part of the user control's visual aspect itself, and what's the actual content of the user control:
<UserControl x:Class="TestSO58234176BackgroundBorder.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:l="clr-namespace:TestSO58234176BackgroundBorder"
mc:Ignorable="d"
Padding="5"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Template>
<ControlTemplate TargetType="{x:Type l:UserControl1}">
<Grid>
<Rectangle Fill="Black" Margin="5"/>
<ContentPresenter/>
</Grid>
</ControlTemplate>
</UserControl.Template>
<Viewbox Stretch="Fill">
<TextBlock Text="This is a test" Foreground="LightGreen" FontWeight="Bold"/>
</Viewbox>
</UserControl>

StackPanel in StatusBar won't stretch

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.

Docking a Dock Panel In Wpf

I have been trying to dock a dock panel.But couldn't.Generally in windows forms if we dock a panel it will fit correctly. i searched in google which shows only for docking the buttons in dock panel.
<Window x:Class="WpfApplication1.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">
<Grid>
<DockPanel>
<DockPanel DockPanel.Dock="Left" Background="Azure">
<TextBlock Width="600"></TextBlock>
</DockPanel>
<DockPanel DockPanel.Dock="Right" Background="Black"></DockPanel>
<DockPanel DockPanel.Dock="top" Background="Cornsilk"></DockPanel>
</DockPanel>
</Grid>
The elements you're binding to the right and top are empty ...
So, you get the one you set the width to to the left (600), then the right one takes width = 0, and the last element fills the rest (since the default for LastChildFill is true), hence you see the Cornsilk color filling everything else.
Seems to work :)
You can also set the LastChildFill to false in the dockpanel like this:
<DockPanel LastChildFill="true">
and then you won't even see the Cornsilk, since it's size is zero as well.

Why is this button cut off?

In the following XAML code the button text is half missing. I can change the Margin property and it becomes obvious that after 250px the content is hidden. Why is that, and how can I fix it?
<Window x:Class="InnerInterface.InventoryManagement" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="someWindow" Height="500" Width="500">
<DockPanel HorizontalAlignment="Left" Name="dockPanel1" VerticalAlignment="Top">
<Grid DockPanel.Dock="Top">
<Button Name="buttonReturnToMainMenu" Content="someButton" Margin="200,0" Width="125" />
</Grid>
</DockPanel>
</Window>
You have a horizontal margin of 200, and a button width of 125, which means the total width needed to show the control properly is about 525.
You also have HorizontalAlignment=Left" on your DockPanel, which means it will draw the content at whatever width it needs and align it to the left side of the screen instead of stretching it to fill all available space. This means it is blocking out a space of 200 on either side of the control, and drawing the button in the remaining space. If this remaining space is less than 125, the image will be cropped.
If you switch to HorizontalAlignment="Stretch", then it will draw the control first (with margins), then stretch it's size so it fits all available space, so the entire control gets resized rather than cropped.
You might be interested in reading this MSDN article on Alignment, Margins, and Padding in WPF.
Edit
If you want only the Left margin to be 200, then use Margin="200,0,0,0". Using Margin="200,0" means that both the left and the right Margins will be 200.
Not really sure about your exact problem, but maybe this should help:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="500" Width="500">
<DockPanel HorizontalAlignment="Stretch" Name="dockPanel1" VerticalAlignment="Top">
<Grid DockPanel.Dock="Top" >
<Button Name="buttonReturnToMainMenu" Content="someButton" Width="125" />
</Grid>
</DockPanel>
</Window>
The problem is that the button Margin is set as:
Margin="200,0"
It should be set as:
Margin="200,0,0,0"
This eliminates the margin on the right side and allows the whole button to show.

wpf transparency

I am using a ListBox with a DataTemplate to create the below map legend. I would like to get the ListBox to have a transparent background (where it is now white) and the ListItems to retain their existing white background. The two legends would then appear to float with a transparent gap between.
I have tried setting the ListBox background with a SolidBrush set to 0 opacity but that doesn't seem to work. I understand that items in the tree cannot have transparency that is less than items above in the tree. Is that my issue and how do I resolve?
Thanks
alt text http://www.freeimagehosting.net/uploads/659cd194e7.png
You can set the Background to {x:Null}.
Did you try setting the background color of the ListBox to "Transparent" (literally)?
Here is some code that worked for me:
<Window x:Class="WpfApplication3.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" Background="Blue">
<Grid>
<ListBox x:Name="ListBox1" Margin="12,25,114,97" Background="#00E51A1A">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="4" Height="20" Width="100" Background="Yellow" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Window>

Resources