I am working on a WP7 app. Well on one of the pages I would like to have a question mark available for users to select. Only trouble I am having is keeping it in a set location. If real estate is available, I want it to be at the bottom right corner all the time. But if the user should need to scroll, I want that item to have to be scrolled to as well.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
....
<StackPanel Grid.Row="1">
<Image Source="/Images/question_mark.png" Stretch="None"
VerticalAlignment="Bottom" HorizontalAlignment="Right" />
</StackPanel>
</Grid>
So how can I keep an image/button at the bottom of the page? Do I need to change anything so that it will always be at the bottom if the user needs to scroll? I appreciate your help!
It sounds like you want the image to be on the bottom of the scrollable content. To do so, place a StackPanel inside of a ScrollViewer
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!--TitlePanel contains the name of the application and page title-->
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock x:Name="ApplicationTitle" Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="page name" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
<!--ContentPanel - place additional content here-->
<ScrollViewer x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<StackPanel>
<Rectangle Height="400" Fill="Brown" />
<Rectangle Height="400" Fill="Green" />
<Image Source="/Images/question_mark.png" Stretch="None"
VerticalAlignment="Bottom" HorizontalAlignment="Right" />
</StackPanel>
</ScrollViewer>
</Grid>
Related
I searched around and didn't find similar question on the forum. I have the following WPF code.
<Window x:Class="WpfApp5.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"
xmlns:local="clr-namespace:WpfApp5"
mc:Ignorable="d"
Title="MainWindow" Height="238.788" Width="406.407">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBox TextWrapping="Wrap" Text="TextBox1 should be resized while moving the GridSplitter"/>
<GridSplitter HorizontalAlignment="Stretch" Height="5" Grid.Row="1" />
<StackPanel Grid.Row="2" Orientation="Horizontal" Background="Black">
<TextBlock Padding="5" Text="I want this black section have fixed height while moving the GridSplitter" Foreground="Aqua" VerticalAlignment="Center" />
</StackPanel>
<TextBox Grid.Row="3" TextWrapping="Wrap" Text="TextBox2 should be resized while moving the GridSplitter"/>
</Grid>
</Window>
When the user drags the grid splitter, only the two textbox should be resized. But what I got is like this:
How can I fix this?
Move the StackPanel and the second TextBox into a single Panel:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBox TextWrapping="Wrap" Text="TextBox1 should be resized while moving the GridSplitter"/>
<GridSplitter HorizontalAlignment="Stretch" Height="5" Grid.Row="1" />
<DockPanel Grid.Row="2">
<StackPanel Orientation="Horizontal" Background="Black" DockPanel.Dock="Top">
<TextBlock Padding="5" Text="I want this black section have fixed height while moving the GridSplitter" Foreground="Aqua" VerticalAlignment="Center" />
</StackPanel>
<TextBox TextWrapping="Wrap" Text="TextBox2 should be resized while moving the GridSplitter"/>
</DockPanel>
</Grid>
It's easy, set VerticalAlignment="Center" by the ´StackPanel´
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBox TextWrapping="Wrap" Text="TextBox1 should be resized while moving the GridSplitter"/>
<GridSplitter HorizontalAlignment="Stretch" Height="5" Grid.Row="1" />
<StackPanel Grid.Row="2" Orientation="Horizontal" Background="Black" VerticalAlignment="Center">
<TextBlock Padding="5" Text="I want this black section have fixed height while moving the GridSplitter" Foreground="Aqua" VerticalAlignment="Center" />
</StackPanel>
<TextBox Grid.Row="3" TextWrapping="Wrap" Text="TextBox2 should be resized while moving the GridSplitter"/>
</Grid>
I found that the problem is not because GridSplitter can only split two before and after siblings, it's the wrong RowDefinition! In the code snippet of the question, the first and forth RowDefinition are set to Height="*", which force them to split the additional space evenly. That's why when you drag the splitter and the first and forth row always keep the same height. If I change them according to the following setting, it just works as expected.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="150" />
<RowDefinition Height="5" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBox TextWrapping="Wrap" Text="TextBox1 should be resized while moving the GridSplitter" />
<GridSplitter HorizontalAlignment="Stretch" Height="5" Grid.Row="1" />
<StackPanel Grid.Row="2" Orientation="Horizontal" Background="Black">
<TextBlock Padding="5" Text="I want this black section have fixed height while moving the GridSplitter"
Foreground="Aqua" VerticalAlignment="Center" />
</StackPanel>
<TextBox Grid.Row="3" TextWrapping="Wrap" Text="TextBox2 should be resized while moving the GridSplitter" />
</Grid>
So no need to nest any more.
I have user controls that contains datagrid.
My status bar disappears as soon as grid populates even though I have enough margins and there's empty space at the bottom. What am i doing wrong????
<DockPanel VerticalAlignment="Stretch" LastChildFill="False">
<StackPanel Orientation="Horizontal" DockPanel.Dock="Top" Margin="0,0,0,0">
<controls:ucXXXXSummary x:Name="ucSummary" Margin="20,20,20,30" Height="Auto" Width="Auto"/>
<controls:XXXXUC x:Name="ucXXXX" Margin="20,20,20,30" Height="Auto" Width="Auto"/>
</StackPanel>
<StatusBar DockPanel.Dock="Bottom" Height="25">
<StatusBarItem>
<StatusBarItem>
<TextBlock Name="lblStatus" Text="abc!!!!!!!!!!!"/>
</StatusBarItem>
</StatusBarItem>
</StatusBar>
</DockPanel>
Don't rely on margins to position elements relative to each other. Use an appropriate Panel such as for example a Grid:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<controls:ucXXXXSummary x:Name="ucSummary" Margin="20,20,20,30" />
<controls:XXXXUC Grid.Row="1" x:Name="ucXXXX" Margin="20,20,20,30" />
<StatusBar Grid.Row="2" Height="25">
<StatusBarItem>
<StatusBarItem>
<TextBlock Name="lblStatus" Text="abc!!!!!!!!!!!"/>
</StatusBarItem>
</StatusBarItem>
</StatusBar>
</Grid>
StackPanels don't play well with scrollable content: Horizontal scroll for stackpanel doesn't work
I'm trying to show text in page of application in 3 textblocks. I want to scroll this because the text is dynamically changed and it depends on what we choose in previous page. When I did this like that:
<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!--TitlePanel contains the name of the application and page title-->
<StackPanel Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock Text="Asystent Barmana" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock Name="PageName" Text="page name" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
<ScrollViewer Name="Scroller" HorizontalAlignment="Center" Height="auto" Margin="12,10,10,-1055" Grid.Row="1" VerticalAlignment="Top" Width="460" ManipulationMode="Control" MaxHeight="2500" >
<StackPanel HorizontalAlignment="Left" Height="auto" VerticalAlignment="Top" Width="460">
<TextBlock Name="MissingSkladnik" TextWrapping="Wrap" Height="auto" FontSize="24"/>
<TextBlock Name="Skladniki" TextWrapping="Wrap" Height="auto" FontSize="24"/>
<TextBlock Name="Przepis" TextWrapping="Wrap" Height="auto" FontSize="24"/>
</StackPanel>
</ScrollViewer>
</Grid>
and the text is not so long it work fine. But in several cases the text is longer and some of text is cut off. When I change StackPanel height to, let's say 1950, it dispaly fine, but when I have shorter text, on the end of page is a black nothing to scroll :/
Any thoughts?
PS. I apologize for my english, it's been a while since I used it ;)
Edit:
I read comments and I change stackpanel to grid. I did it like that:
<ScrollViewer Name="Scroller" HorizontalAlignment="Center" Height="auto" Margin="12,10,10,-1055" Grid.Row="1" VerticalAlignment="Top" Width="460" ManipulationMode="Control" MaxHeight="2500" >
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Name="MissingSkladnik" TextWrapping="Wrap" Height="auto" FontSize="24" Grid.Row="0"/>
<TextBlock Name="Skladniki" TextWrapping="Wrap" Height="auto" FontSize="24" Grid.Row="1"/>
<TextBlock Name="Przepis" TextWrapping="Wrap" Height="auto" FontSize="24" Grid.Row="2"/>
</Grid>
</ScrollViewer>
It doesn't work either. If I set the height of stackpanel it works, but when there is small amount of text it doesn't look nice. User can srcoll black empty screen :/
A StackPanel will not resize its content in the same way that a Canvas will not resize its content. However, a Grid control can resize its contents. Try replacing this:
<StackPanel Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock Text="Asystent Barmana" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock Name="PageName" Text="page name" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
with this:
<Grid Name="TitleGrid" Grid.Row="0" Margin="12,17,0,28">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Text="Asystent Barmana"
Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock Grid.Row="1" Name="PageName" Text="page name" Margin="9,-7,0,0"
Style="{StaticResource PhoneTextTitle1Style}"/>
</Grid>
UPDATE >>>
In WPF, setting explicit Height and/or Width dimensions and/or Margins will stop a Control from sizing itself. If you want the ScrollViewer to re-size itself to the size of its content, try remove the explicit layout and dimension values that you have set, eg. Margin.
I have the following XAML source to demonstrate what I am working on.
I want, when resizing the group vertically, is to have the first groupbox expand, up to its max height, then, when that is reached, expand the third groupbox.The third groupbox has a min height property, as well.
<UserControl
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" x:Name="Screen_1_Name"
x:Class="TestExpansionScreens.Screen_1"
Width="400" Height="400">
<Grid x:Name="LayoutRoot" Background="White" Margin="0,0,0,0">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<GroupBox Header="Thing1" Background="LightGreen" Grid.Row="0" Grid.Column="0" MaxHeight="350">
<Button Content="Stuff1" />
</GroupBox>
<GroupBox Header="Thing2" Background="LightBlue" Grid.Row="1" Grid.Column="0">
<TextBox Text="Stuff2" Height="60" />
</GroupBox>
<GroupBox Header="Thing3" Background="Pink" Grid.Row="2" Grid.Column="0">
<TextBox Text="Stuff3" />
</GroupBox>
</Grid>
</UserControl>
Normally, when I just want a single control expanded to fill the available space, I use a DockPanel. I've built this example with all kinds of assortments of grids and dockpanels, however, I have been unable to resolve how to make it work. Any idea on how to make it happen?
Thanks
You have to set the MaxHeight on your first RowDefinition, not on the GroupBox. The row will grow up to that height and then all excess space will be occupied by the third row. You can also add a MinHeight to the third row.
<Grid x:Name="LayoutRoot" Background="White" Margin="0,0,0,0">
<Grid.RowDefinitions>
<RowDefinition MaxHeight="350" />
<RowDefinition Height="Auto"/>
<RowDefinition MinHeight="150" />
</Grid.RowDefinitions>
<GroupBox Header="Thing1" Background="LightGreen" Grid.Row="0" Grid.Column="0">
<Button Content="Stuff1" />
</GroupBox>
<GroupBox Header="Thing2" Background="LightBlue" Grid.Row="1" Grid.Column="0">
<TextBox Text="Stuff2" Height="60" />
</GroupBox>
<GroupBox Header="Thing3" Background="Pink" Grid.Row="2" Grid.Column="0">
<TextBox Text="Stuff3" />
</GroupBox>
</Grid>
In Winforms, I use Fill and Dock to achieve this.
I have a "Page" where I would like to play a video file and also show the label at the bottom. I would like the page to be able to stretch and for the video to stretch and to have the label stay at the bottom of the page.
My attempts so far always results in the video covering the label when it is played. How can this be fixed?
(Other controls in the StackPanel have been omitted)
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.MediaElementExample" >
<DockPanel LastChildFill="True">
<MediaElement Source="media\numbers.wmv" Name="myMediaElement"
LoadedBehavior="Manual" UnloadedBehavior="Stop"
MediaOpened="Element_MediaOpened" MediaEnded="Element_MediaEnded"
DockPanel.Dock="Top" Margin="50" />
<StackPanel HorizontalAlignment="Center" Orientation="Horizontal"
Height="30" DockPanel.Dock="Bottom" Margin="50">
<TextBlock Margin="5" VerticalAlignment="Center">
Video Label
</TextBlock>
</StackPanel>
</DockPanel>
</Page>
Solution (with thanks to Daniel May):
<Grid Height="Auto">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="30"/>
</Grid.RowDefinitions>
<MediaElement Source="media\numbers.wmv" Name="myMediaElement" LoadedBehavior="Manual" UnloadedBehavior="Stop"
MediaOpened="Element_MediaOpened" MediaEnded="Element_MediaEnded" />
<StackPanel HorizontalAlignment="Center" Orientation="Horizontal" Height="30" Grid.Row="1">
<Button Content="Button" Height="23" Name="button1" Width="75" Click="button1_Click" />
</StackPanel>
</Grid>
You can achieve this using a Grid.
<Grid Height="300" Width="300">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<MediaElement Source="media\numbers.wmv"
Name="myMediaElement"
LoadedBehavior="Manual"
UnloadedBehavior="Stop"
MediaOpened="Element_MediaOpened"
MediaEnded="Element_MediaEnded" />
<TextBlock Margin="5"
Grid.Row="1"
VerticalAlignment="Center"
Text="Video Label" />
</Grid>
Using the Height attribute on the second RowDefinition, you force that row to size to it's contents. The preceding RowDefinition then fills the rest of the available space (in your case, your MediaElement).