Dockpanel Fix Bottom Child - c#

I'm trying to build a layout that would fix the bottom of two rows to be always visible. the problem is, the content of the bottom row has to be at the top, which makes it difficult to use a dockpanel. here's a short overview:
here is a link with pictures for all the windows:
(sorry about that, but stackoverflow won't let me post images yet..)
the first window is how it's supposed to look when there's plenty space available, the bottom (blue) sticks to the top (red).
the code looks like this:
<DockPanel>
<Grid VerticalAlignment="Top"
Background="Red"
DockPanel.Dock="Top">
<Grid Height="100" />
</Grid>
<Grid Height="20"
Background="Blue"
VerticalAlignment="Top"
DockPanel.Dock="Bottom" />
</DockPanel>
but when I size the window so the second row doesn't fit anymore, the second row is not fixed and will be invisible when the window is too small: window 2
so what I want is something like this:
<DockPanel>
<Grid Height="20"
Background="Blue"
DockPanel.Dock="Bottom" />
<Grid VerticalAlignment="Top"
Background="Red"
DockPanel.Dock="Top">
<Grid Height="100" />
</Grid>
</DockPanel>
which gives me the following with enough space available: window 3
and this when I resize the window: window 4
the bottom is fixed. The problem here is, when there's too much space, the second row doesn't stick to the top, but to the bottom like in the third picture.
I've played around with DockPanel.LastChildFill and the child order in a dockpanel. I've tried various layouts using one or more grids but couldn't get it to work.
how would I go about doing this?
edit:
#publicgk:you're right, the second window was the wrong one, I updated the link.
Moreover, I'll try to explain myself a little better.
Considering the first row is completely red, and the second row is the rest (blue and white together). Then the first code sample gives me the first and the second window: While the content of the second row (the blue part) is at the top (window1, which is what I want), the second row is not fixed/always visible when i resize the window (window 2).
The second code sample produces window 3 and 4, while the content is at the bottom of the second row when the window is big enough (window 3, not what I want), the second row is visible even when I resize the window (window 4, that's what i want), so the second row is overlapping the first.
To sum it up i need the rows to behave like window 1 when there's enough space, and like window 4 when there's not.
Edit2: I forgot to mention, the first row is supposed to hold contents, of which the size is unknown and variable, so using a grid and setting height or maxheight of the first row won't work. the height of the second row however is known and may be set directly.
here's a sample, which shows this problem:
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication2"
Title="MainWindow"
Width="525"
Height="350">
<Window.Resources>
<local:RandomHeightConverter x:Key="RandomHeightConverter"/>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="100*" MaxHeight="100"/>
<RowDefinition Height="20" />
</Grid.RowDefinitions>
<Grid Grid.Row="0" Background="Red" Height="{Binding Converter={StaticResource RandomHeightConverter}}" />
<Grid Grid.Row="1" Background="Blue" />
</Grid>
public class RandomHeightConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return new Random().Next(20, 100);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
that would produce results like this:
variable first row problem

Not sure if you can do this layout using DockPanel, but you may be able to use Grid to do this sort of layout.
Something like this replicates what you are trying to do
<Window x:Class="WpfApplication9.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication9"
Title="MainWindow" Height="209" Width="525" Name="UI">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="100*" MaxHeight="100" />
<RowDefinition Height="20" />
</Grid.RowDefinitions>
<Grid Grid.Row="0" Background="Red" />
<Grid Grid.Row="1" Background="Blue" />
</Grid>
</Window>
Or bind the RowDefinition sizes to the contents you want to show, so in the below example the top sction will size to fix its contents but can shrink, the bottom row is fixed size to the bottom content and will overlap when the window is sized smaller than the Top row.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" MaxHeight="{Binding ElementName=topContent, Path=ActualHeight, Mode=OneTime}" />
<RowDefinition Height="{Binding ElementName=bottomContent, Path=ActualHeight,Mode=OneTime}" />
</Grid.RowDefinitions>
<Grid x:Name="topContent" Grid.Row="0" >
<!--your top content-->
<Grid Height="200" Background="Red" />
</Grid>
<Grid Grid.Row="1" >
<!--your bottom content-->
<Grid x:Name="bottomContent" VerticalAlignment="Top" Height="20" Background="Blue" />
</Grid>
</Grid>
Result:

Related

Full size content dialog uwp

I want to create a content dialog with full width and height but i have a problem with set the width for all screen sizes and keep the button on the bottom
and Here's my code
<ContentDialog
x:Class="app.Content_Dialog.WhatsNew"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:app.Pages"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Name="dialog2" Height="Auto" Width="Auto" FullSizeDesired = "True" MaxWidth="600">
<Grid Height="800" Width="Auto">
<Grid VerticalAlignment="Stretch" Margin="-24,0,0,165" >
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<!-- Take as much as needed -->
<RowDefinition Height="Auto" />
<!-- Take exactly 20 DIP -->
<RowDefinition Height="*" />
<!-- Take all the rest -->
</Grid.RowDefinitions>
<Button x:Name="close" VerticalAlignment="Bottom" Content="close" Height="102" Width="374" HorizontalAlignment="Right" Grid.Row="2"/>
</Grid>
</Grid>
I'm trying to create something like this content dialog on MSPoweruser app
Here's a picture for it
You shouldn't define a Close Button inside your content Grid, instead, use the CloseButton that's built within the ContentDialog itself.
So just remove the Button and the Margin on your Grid, and
if you only target Windows 10 build 15063 and onward
add CloseButtonText="Close" to your ContentDialog;
if you target anything before 15063
add SecondaryButtonText="Close" instead.
If you want the CloseButton to take up the space horizontally, you need to apply a custom style to your ContentDialog, locate the container of the Buttons and remove its column definitions.

How to control the height of WPF Application window based on the contents of dynamic Grid

I have created a WPF application that generate tiles in the second row of grid. What i'm trying to achieve is to keep rendering tiles in the second row without showing the vertical scroll bar, until unless the height of WPF application crosses the resolution of user screen.
<Window x:Class="ABC.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ABC Installation" MinWidth="620" SizeToContent="WidthAndHeight" AllowsTransparency="True" WindowStyle="None" Loaded="MainWindow_loaded" MinHeight="600" >
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="60" />
<RowDefinition Height="56" />
<RowDefinition Height="Auto" ScrollViewer.IsDeferredScrollingEnabled="True" />
<RowDefinition Height="94"/>
</Grid.RowDefinitions>
</Grid>
<ScrollViewer Name="productsOuterScroll" Grid.Row="2" HorizontalScrollBarVisibility="Hidden" ScrollViewer.VerticalScrollBarVisibility="Auto" Grid.RowSpan="1" >
<StackPanel x:Name="FormStackPanel">
</StackPanel>
</ScrollViewer>
This code renders all the tiles exceeding the user screen window height without a vertical scroll bar.
Any idea how to do this? Any help would be appreciated.
If you want the content to scroll, remove the Height from the RowDefinition of the row that you are adding content to, and put the content inside the ScrollViewer.
Your window might be sizing correctly to the vertical resolution of the screen, but if it's displayed in the center of the screen, it will exceed the height. You can set the startup location to top of the screen with:
WindowStartupLocation="Manual" Top="0"
If the window height is too high, you might want to set maximum height for your window.
I figured out the mistake. Only two things needed to be done.
remove the height attribute from row definition so it should look like this
<Window x:Class="ABC.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ABC Installation" MinWidth="620" SizeToContent="WidthAndHeight" AllowsTransparency="True" WindowStyle="None" Loaded="MainWindow_loaded" MinHeight="600" >
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="60" />
<RowDefinition Height="56" />
<RowDefinition ScrollViewer.IsDeferredScrollingEnabled="True" />
<RowDefinition Height="94"/>
</Grid.RowDefinitions>
<ScrollViewer Name="productsOuterScroll" Grid.Row="2" HorizontalScrollBarVisibility="Hidden" ScrollViewer.VerticalScrollBarVisibility="Auto" Grid.RowSpan="1" >
<StackPanel x:Name="FormStackPanel">
</StackPanel>
</ScrollViewer>
</Grid>
Setting the max Height dynamically according to the users primary screen height in .cs file
double userheightscreen = System.Windows.SystemParameters.PrimaryScreenHeight;
this.MaxHeight = userheightscreen - 100;
PS: "-100" is just to leave some space on top and bottom of the screen.

C# WinRT Make a Control size fill its parent

I'm an experienced developer, but new to C# and the Windows Runtime. I'm trying to create a custom UserControl (a specialized button) that can be dynamically sized. My button should have three rows of text on it (Top, Middle, Bottom) which are given proportional sizes (1*, 3*, 1*). I want the textboxes to fill their given space in the grid. i.e. If the button is 500x200, then the internal TextBoxes would all be 200 wide, the Top one would be 100 pixels tall, the Middle would be 300 tall, and the bottom would be 100 tall. If the button is 700x300, Top=140, Middle=420, Bottom=140.
I created a Grid with proportionally sized Rows and it behaves the way I want, but I don't know how to get the child elements in the grid to fill their space in the grid cell.
<UserControl
x:Class="DynamicButtons.DynamicButton"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:DynamicButtons"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">
<Grid Background="SlateGray">
<Grid.RowDefinitions>
<RowDefinition Height="1*" />
<RowDefinition Height="3*" />
<RowDefinition Height="1*" />
</Grid.RowDefinitions>
<TextBox Text="Top" Grid.Row="0" Margin="0,0,0,0" TextAlignment="Center" />
<TextBox Text="Middle" Grid.Row="1" Margin="0,0,0,0" TextAlignment="Center" />
<TextBox Text="Bottom" Grid.Row="2" Height="Auto" Margin="0,0,0,0" TextAlignment="Center" />
</Grid>
</UserControl>
If you add VerticalAlignment="Stretch" to your TextBox definitions, they'll fill the vertical space.

How to anchor a wpf data grid which is inside a stack panel a fixed distance from the main window's four corners

I have the following wpf layout given to me by my employer. It makes use of multiple nested stack panels.
I'm trying to anchor a data grid which is inside a stack panel a fixed distance away from the main window's four corners. And whenever the grid contains data of which some of it is hidden because of the parent window's size, it is supposed to display scroll bars which must disappear if not needed.
I set the data grid's and the stack panel's width to Auto so that it fills the width and that makes the horizontal and vertical scroll bars behave as i want them to. BUT the grid doesn't have the required height.
But when i try to set the data grid's height property to auto both the horizontal and vertical scroll bars disappear resulting in hidden data.
I tried setting the data grids height property to a fixed size and updating it whenever the window is resized but the scroll bars are still hidden how can i fix this?
<UserControl x:Class="WpfApplication1.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"
mc:Ignorable="d"
d:DesignHeight="441" d:DesignWidth="300">
<Grid>
<StackPanel Margin="0" Name="stackPanel1">
<ListBox Height="100" Name="listBox1" Width="253" />
<Button Content="Button" Height="23" Name="button1" Width="256" Click="button1_Click" />
<StackPanel Name="stackPanel2">
<StackPanel Height="34" Name="stackPanel3" Width="249" />
<DataGrid AutoGenerateColumns="False" Name="dataGrid1" Height="282" />
</StackPanel>
</StackPanel>
</Grid>
</UserControl>
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:my="clr-namespace:WpfApplication1" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" x:Class="WpfApplication1.MainWindow"
Title="MainWindow" Height="502" Width="525" StateChanged="Window_StateChanged">
<Grid Margin="0">
<my:UserControl1 x:Name="userControl11" Loaded="userControl11_Loaded" />
</Grid>
</Window>
I don't understand all this StackPanel inside StackPanel stuff. You should simply use Grid for your layout:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<ListBox Grid.Row="0" Height="100" Name="listBox1" Width="253" />
<Button Grid.Row="1" Content="Button" Height="23" Name="button1" Width="256" />
<StackPanel Grid.Row="2" Height="34" Name="stackPanel3" Width="249" />
<DataGrid Grid.Row="3" AutoGenerateColumns="False" Name="dataGrid1" />
</Grid>
And having an empty StackPanel stackPanel3 as spaceholder seems awkward. Thats what WPF elements have a Margin property for.
When you put items into a vertical StackPanel they like to pretend they have infinite vertical space. Switch over to specifying rows on your Grid, and place your DataGrid in one of those rows. When it's inside a Grid it knows how much space it has available and should show the scrollbars appropriately.

ListBox is contained in a ScrollViewer

I would like the ScrollViewer of the page to be displayed when all the information cannot be shown on the screen (i.e. resize the window)
However, the ListBox here doesn't get a scroll and it gets sketch till the bottom of the page unless i set it to have a MaxSize. Is there a way to give priority to the ListBox to display its ScrollViewer before the one I have made?
what i have right now
http://i.imgur.com/bEJcz.png
what i would like to achieve, but i used a MaxHeight for the ListBox here.
Here's some my markup:
<ScrollViewer HorizontalAlignment="Stretch" VerticalScrollBarVisibility="Auto" Name="scrollViewer1" VerticalAlignment="Stretch" >
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ComboBox Grid.Row="0" Width="120" HorizontalAlignment="Left"></ComboBox>
<ListBox HorizontalAlignment="Left" Name="listBox" Width="120" Grid.Row="1" <!--MaxHeight="500"--> />
</Grid>
</ScrollViewer>
I know this question is old, but I had exactly the same problem and came up with a bit of a hack as a fix but its better than having the question unsolved.
Much of what I've read states that using things like StackPanel is bad in this case because the panel grows to fit the elements it holds. Normally this works fine because you can stick the StackPanel into a Grid and set the MinHeight and MaxHeight of the column/row and lock the controls in place. As soon as the ScrollView is added this kind of goes to hell. The answer above describes the problem well, but lacks a solution.
I tried many different types of Panels instead of a StackPanel but they all yield the same result. I decided that since my ListBox sits inside of a Grid, I needed to bind the MaxHeight of that grid location to some other value in the control to keep the ListBox from growing. The problem with this is that there is no element that you can bind straight to and get the exact height your looking for.
Enter the hack:
My height was just a tiny bit too big creating a weird always offscreen ListBox (in fact 36 pixels too large, which was the height of the label above the ListBox). So I implemented the IValueConverter:
class HeightToAdjustedHeightConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var height = (double) value - 33d;
return height < 360d ? 360d : height;
//360 being the minimum height allowed for the listbox
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
}
All I did after that was include it as a converter for the binding on MaxHeight (Note you need to name your usercontrol and bind to its x:Name):
<Grid Grid.Column="0"
Grid.Row="1"
VerticalAlignment="Top"
ClipToBounds="True"
MaxHeight="{Binding ElementName=AdHocUserControl, Path=ActualHeight, Converter={StaticResource HeightToAdjustedHeightConverter}}">
The only other alternative I can think of is to extend one of the panels and try to play with its growth behavior. I admit this is a hack, but it will work.
Try this
<ScrollViewer HorizontalAlignment="Stretch" VerticalScrollBarVisibility="Auto" Name="scrollViewer1" VerticalAlignment="Stretch" >
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ComboBox Grid.Row="0" Width="120" HorizontalAlignment="Left" ></ComboBox>
<ListBox HorizontalAlignment="Left" Name="listBox" Width="120" VerticalAllignment = "Top" Grid.Row="1"/>
</Grid>
</ScrollViewer>
Or you can also try this
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ComboBox Grid.Row="0" Width="120" HorizontalAlignment="Left" ></ComboBox>
<ListBox HorizontalAlignment="Left" Name="listBox" VerticalAlignment= "Top" Width="120" Grid.Row="1" ScrollViewer.VerticalScrollBarVisibility="Auto"/>
</Grid>
You have a logical inconsistency in your definitions.
The requirement as you put it: "I would like the scrollviewer of the page to be displayed when all the information cannot be shown on the screen [without using MaxHeight]" - a question arises: "How do you determine that 'all the information cannot be shown on the screen'?" or "At what point the ListBox should stop growing and show the scroll bar?".
From a WPF\Silverlight layout management logic, it does exactly what you want - when the sum of height of list box plus the height of the combo box is greater than the ViewportHeight of the scroll viewer - you get a scroll bar. That is possible only when you allow the ListBox to grow to it's desired size without scroll bars.
Dont set the MaxHeight on the ListBox, just use the star '*' notation in your RowDefinitions to get the relative sizing between your 2 controls correct.
Another solution:
<ScrollViewer HorizontalAlignment="Stretch" VerticalScrollBarVisibility="Auto" Name="scrollViewer1" VerticalAlignment="Stretch" >
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ComboBox Grid.Row="0" Width="120" HorizontalAlignment="Left"></ComboBox>
<ScrollViewer x:Name="scrollViewer" Grid.Row="1" ScrollViewer.VerticalScrollBarVisibility="Disabled" >
<ListBox HorizontalAlignment="Left" Name="listBox" Width="120" Grid.Row="1" MaxHeight="{Binding ActualHeight, ElementName=scrollViewer}" ScrollViewer.VerticalScrollBarVisibility="Auto"/>
</ScrollViewer>
</Grid>

Categories