Why doesn't the grid layout work without specifying RowDefinitions and Column Definitions? - xaml

<Page
x:Class="AllControls.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:AllControls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<Rectangle Width="100" Height="100" Fill="Red" Grid.Column="0" Grid.Row="0"/>
<Rectangle Width="100" Height="100" Fill="Orange" Grid.Column="1" Grid.Row="0"/>
<Rectangle Width="100" Height="100" Fill="Yellow" Grid.Column="0" Grid.Row="1"/>
<Rectangle Width="100" Height="100" Fill="Green" Grid.Column="1" Grid.Row="1"/>
<Rectangle Width="100" Height="100" Fill="Blue" Grid.Column="0" Grid.Row="2"/>
<Rectangle Width="100" Height="100" Fill="Indigo" Grid.Column="1" Grid.Row="2"/>
<Rectangle Width="100" Height="100" Fill="Violet" Grid.Column="0" Grid.Row="3"/>
<Rectangle Width="100" Height="100" Fill="Purple" Grid.Column="1" Grid.Row="3"/>
</Grid>
</Page>
I am providing, Row Number and Column number for each element in this case Rectangles. I have also provided height and width for each of them.
I come from an HTML background.
Can someone explain to me how the tags RowDefinitions and ColumnDefinitions work here ?

You have to specify RowDefinitions and ColumnDefinitions so that it knows how to size the rows and columns. Otherwise it doesn't know whether you want auto-sizing or star-sizing. And it also needs to know how many rows and columns you need up front; it doesn't add them on the fly based on your values of Grid.Row and Grid.Column.
I think the code you wrote looks reasonable, and it would be nice if it used a default when you don't specify, but unfortunately it doesn't. Instead, it builds a single-column, single-row grid and stacks all the children on top of each other.
I can think of a couple ways to write some XAML that will do what you want.
One way:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Rectangle Width="100" Height="100" Fill="Red" Grid.Column="0" Grid.Row="0"/>
<Rectangle Width="100" Height="100" Fill="Orange" Grid.Column="1" Grid.Row="0"/>
...
</Grid>
Another way:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="100" />
<RowDefinition Height="100" />
<RowDefinition Height="100" />
<RowDefinition Height="100" />
</Grid.RowDefinitions>
<Rectangle Fill="Red" Grid.Column="0" Grid.Row="0"/>
<Rectangle Fill="Orange" Grid.Column="1" Grid.Row="0"/>
...
</Grid>

Like Mr. Andrew pointed out, you'll have to define your layout more to accomplish it using specified RowDefinition / ColumnDefinition to basically manually lay your stuff out. If you're looking for something a bit more fluid with less requirement for defining your layout structure you should look into GridView / VariableSizeWrapGrid (I think is more of what you're looking for.)
Both of which have multiple examples available around the web and are pretty simple to get used to. Hope this helps on your transition from HTML to XAML (ps, in my opinion XAML > HTML)
:)

Related

How to put those 3 buttons on the center of bottom?

In UWP xaml design as below, I split the whole screen to 3 columns and 3 rows. And For row 2 column 1, I need to put a canvas which contains a RelativePanel inside of it. And there will some buttons inside of the panel. My purpose is to make an animation on the panel.
I hope to put those 3 buttons on the bottom/center of the screen, but failed. My layout picture is attached, but it is not what I want.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="10*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="2*" />
<RowDefinition Height="15*" />
<RowDefinition Height="3*"/>
</Grid.RowDefinitions>
<Canvas x:Name="toolbarCanvas" Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="3" HorizontalAlignment="Center">
<RelativePanel x:Name="toolbarPanel">
<Button x:Name="bt1" Margin="50,0,50,0" Height="100" Width="100" VerticalAlignment="Center" RelativePanel.LeftOf="bt2"/>
<Button x:Name="bt2" Margin="50,0,50,0" Height="100" Width="100" VerticalAlignment="Center" RelativePanel.AlignHorizontalCenterWithPanel="True"/>
<Button x:Name="bt3" Margin="50,0,50,0" Height="100" Width="100" VerticalAlignment="Center" RelativePanel.RightOf="bt2" />
</RelativePanel>
</Canvas>
</Grid>
How to put those 3 buttons on the center of bottom?
Canvas is a layout panel that supports absolute positioning of child elements relative to the top left corner of the canvas.
<Canvas Width="640" Height="480" >
<Rectangle Canvas.Left="30" Canvas.Top="30"
Fill="Red" Width="200" Height="200" />
</Canvas>
For your requirement. Please use Grid panel to replace Canvas and set toolbarPanel VerticalAlignment HorizontalAlignment property like the follow.
<Grid x:Name="toolbarGrid" Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="3" HorizontalAlignment="Center">
<RelativePanel x:Name="toolbarPanel" VerticalAlignment="Bottom" HorizontalAlignment="Center">
<Button x:Name="bt1" Margin="50,0,50,0" Height="100" Width="100" VerticalAlignment="Center" RelativePanel.LeftOf="bt2"/>
<Button x:Name="bt2" Margin="50,0,50,0" Height="100" Width="100" VerticalAlignment="Center" RelativePanel.AlignHorizontalCenterWithPanel="True"/>
<Button x:Name="bt3" Margin="50,0,50,0" Height="100" Width="100" VerticalAlignment="Center" RelativePanel.RightOf="bt2" />
</RelativePanel>
</Grid>

Making fixed-width grid columns and rows in UWP

I am making an application and I want certain grid rows and columns to be fixed, while others resize to fit the window. My problem is that I cannot do this in Universal Apps.
In WPF, the solution is simple:
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="50" /> <!-- This row is a fixed height -->
<RowDefinition Height="*" MinHeight="200" /> <!-- This row is resizeable, but has a minimum height -->
<RowDefinition Height="100" />
<RowDefinition Height="20" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20" /> <!-- This column has a fixed width -->
<ColumnDefinition Width="*" MinWidth="300" /> <!-- These rows are resizeable, but have minimum widths -->
<ColumnDefinition Width="*" MinWidth="300" />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
</Grid>
When I try this in UWP, the rows and columns with fixed sizes resize while the others with asterisks stay fixed. I tried putting asterisks on the fixed rows and columns and removing the pre-existing ones. I thought that in UWP it was reversed, however this severely messed up my app and made it worse.
My solution was to try the following in UWP:
<Grid x:Name="pageGrid"
Background="White">
<Grid.RowDefinitions>
<RowDefinition MaxHeight="20"
MinHeight="20"/>
<RowDefinition Height="*"/>
<RowDefinition MaxHeight="20"
MinHeight="20"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition MaxWidth="20"
MinWidth="20"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition MaxWidth="260"
MinWidth="260"/>
<ColumnDefinition MaxWidth="20"
MinWidth="20"/>
</Grid.ColumnDefinitions>
</Grid>
The idea here is to have fixed margins around my controls, at 20 pixels width. Inside these margins there are two boxes: One has a fixed width and resizable height, and the other resizes in both directions.
Despite this, I again experienced the same problem where the margins resize but the 'resizable' boxes do not.
Is there actually a way to have fixed and resizeable rows and columns in a grid using Universal Windows Platform? So far, i have yet to find evidence of this.
Complete code:
<Page
x:Class="UniversalCamera.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:UniversalCamera"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
MinWidth="800"
MinHeight="450"
Width="800"
Height="450">
<Grid x:Name="pageGrid"
Background="White">
<Grid.RowDefinitions>
<RowDefinition MaxHeight="20"
MinHeight="20"/>
<RowDefinition Height="*"/>
<RowDefinition MaxHeight="20"
MinHeight="20"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition MaxWidth="20"
MinWidth="20"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition MaxWidth="260"
MinWidth="260"/>
<ColumnDefinition MaxWidth="20"
MinWidth="20"/>
</Grid.ColumnDefinitions>
<Border BorderThickness="2"
BorderBrush="Black"
CornerRadius="5"
Grid.Column="1"
Grid.Row="1"
Grid.ColumnSpan="2"
Margin="-10,-10,-10,-10"/>
<Border BorderThickness="2"
BorderBrush="Black"
CornerRadius="5"
Grid.Column="1"
Grid.Row="1"
Margin="2,2,2,2">
<Image x:Name="imageFrame"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"/>
</Border>
<Canvas x:Name="controlCanvas"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Grid.Column="2"
Grid.Row="1">
<StackPanel x:Name="controlStack"
Canvas.Top="0"
Canvas.Left="0"
Width="260"
Orientation="Vertical">
<Button x:Name="startLiveButton"
Width="200"
Margin="0,5,0,0"
HorizontalAlignment="Center"
Content="Start Live"
Click="startLiveButton_Click"/>
<Button x:Name="stopLiveButton"
Width="200"
Margin="0,5,0,0"
HorizontalAlignment="Center"
Content="Stop Live"
Click="stopLiveButton_Click"/>
<Button x:Name="freezeVideoButton"
Width="200"
Margin="0,5,0,0"
HorizontalAlignment="Center"
Content="Freeze Video"
Click="freezeVideoButton_Click"/>
<Button x:Name="loadParameterButton"
Width="200"
Margin="0,5,0,0"
HorizontalAlignment="Center"
Content="Load Parameter"
Click="loadParameterButton_Click"/>
<CheckBox x:Name="autoWhiteCheckbox"
HorizontalAlignment="Center"
Width="200"
Margin="0,25,0,0"
Content="Auto White Balance"
Checked="autoWhiteCheckbox_Checked"
Unchecked="autoWhiteCheckbox_Unchecked"/>
<CheckBox x:Name="autoGainCheckbox"
HorizontalAlignment="Center"
Width="200"
Margin="0,5,0,0"
Content="Auto Gain Balance"
Checked="autoGainCheckbox_Checked"
Unchecked="autoGainCheckbox_Unchecked"/>
</StackPanel>
</Canvas>
</Grid>
</Grid>
</Page>
This code is intended to have extra rows and columns as margins around the main controls. These should be fixed at 20 pixels. When I run the code the margins stretch and the central boxes stay fixed; this is the opposite of what I intended:
(The black outlined area stays the same size when the window is resized while the margins stretch to fit the window.)
Your main Grid is fixed at 800 x 450 px. If you remove that restriction, the grid will stretch appropriately
Updated code:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
MinWidth="800"
MinHeight="450">
<Grid x:Name="pageGrid"
...

Grid adding unwanted extra vertical space

I have the following xaml inside a user control:
<StackPanel VerticalAlignment="Top">
<Grid Background="LimeGreen">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Rectangle Grid.Column="0" Grid.Row="0" Grid.RowSpan="3" VerticalAlignment="Top" Fill="Yellow" Width="80" Height="80" />
<Rectangle Grid.Column="1" Grid.Row="0" VerticalAlignment="Top" Fill="Red" Width="10" Height="10" />
<Rectangle Grid.Column="1" Grid.Row="1" VerticalAlignment="Top" Fill="Red" Width="10" Height="10" />
<Rectangle Grid.Column="1" Grid.Row="2" VerticalAlignment="Top" Fill="Red" Width="10" Height="10" />
</Grid>
</StackPanel>
and it produces the following layout:
For some reason, this is adding extra unwanted space after the yellow square. I want the following layout instead:
The extra space only occurs when the green grid is inside a stack panel. I can get the correct layout by either:
Putting the green grid inside a grid instead of a stack panel.
Or setting the width of the second column to "Auto". This is undesired, though.
My questions are:
Is the layout in the first picture correct/expected? If so, why is it adding the extra space?
Why does setting the width of the second column to "Auto" get rid of the extra vertical space?
How can I get layout #2 inside a stack panel with width of second column set to * (star)?
I can answer question 3 with this alternative xaml, however it uses a nested grid to bypass using a row span for the yellow square. Ideally this should be possible using just one grid. Anyway, here's the xaml:
<StackPanel VerticalAlignment="Top">
<Grid Background="LimeGreen">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Rectangle VerticalAlignment="Top" Fill="Yellow" Width="80" Height="80" />
<Grid Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Rectangle Grid.Row="0" VerticalAlignment="Top" Fill="Red" Width="10" Height="10" />
<Rectangle Grid.Row="1" VerticalAlignment="Top" Fill="Red" Width="10" Height="10" />
<Rectangle Grid.Row="2" VerticalAlignment="Top" Fill="Red" Width="10" Height="10" />
</Grid>
</Grid>
</StackPanel>
I'm still stumped on answering questions 1 and 2.

Detect grid upon grid in XAML

I have 2 Grids in XAML. One small and one big. How I can detect that, after first move, it upon second? I need smth like coordinates (need to align the first grid to the second grid's border or to other grids in this 'big-grid'). What're methods, properties?
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<Grid HorizontalAlignment="Center" VerticalAlignment="Center" x:Name="Parent" Margin="124,340,1042,228">
<Grid.RowDefinitions>
<RowDefinition Height="100"/>
<RowDefinition Height="100"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
<Grid Grid.Column="0" ManipulationDelta="Object_ManipulationDelta" x:Name="Figure" ManipulationMode="All">
<Rectangle Fill="Red" Width="40" Height="40"/>
<Rectangle Fill="Red" Width="40" Height="40" Margin="-10,30,70,30"/>
<Rectangle Fill="Red" Width="40" Height="40" Margin="-10,70,70,-10"/>
<Rectangle Fill="Red" Width="40" Height="40" Margin="-50,70,110,-10"/>
<Grid.RenderTransform>
<CompositeTransform/>
</Grid.RenderTransform>
</Grid>
</Grid>
<Grid x:Name="Field" Width="500" Height="700">
<Rectangle Fill="Black" Width="40" Height="40" Margin="10,10,450,650" StrokeThickness="1" Stroke="#FF1B1B1B"/>
<Rectangle Fill="Black" Width="40" Height="40" Margin="50,10,410,650" StrokeThickness="1" Stroke="#FF1B1B1B"/>
<Rectangle Fill="Black" Width="40" Height="40" Margin="90,10,370,650" StrokeThickness="1" Stroke="#FF1B1B1B"/>
<!--many rectangles-->
</Grid>
</Grid>
I move Grid Figure to Grid Field. In future I may be change rectangle to border.
To detect the relative position between Figure and Field, you can use something like that:
var transform= Field.TransformToVisual(Figure);
Point relativePosition = transform.TransformPoint(new Point(0,0));
relativeCoordinate will be the distance between the Top Left of Field and the Top left of Figure
if you want the absolute coordinate of the Grid you can do this:
var transform= this.TransformToVisual(Figure);
Point absolutePositionFigureGrid = transform.TransformPoint(new Point(0,0));

GridSplitter in a Frame; expand beyond border problems

I've got a generic view for displaying data in a Silverlight RIA application. Basically, the view takes in a parameter which is the query required by RIA to get the data, and the data is displayed using autogenerated fields.
Here's part of the XAML code for the view.
<Grid Grid.Column="0">
<Grid.RowDefinitions>
<RowDefinition x:Name="DataGridRow"/>
<RowDefinition Height="Auto"/>
<RowDefinition x:Name="DataFormRow"/>
<RowDefinition Height="Auto" x:Name="EditRow"/>
</Grid.RowDefinitions>
<ria:DomainDataSource Name="SQLDomainDataContext" LoadingData="SQLDomainDataContext_LoadingData" LoadSize="45" SubmittedChanges="SQLDomainDataContext_SubmittedChanges" SubmittingChanges="SQLDomainDataContext_SubmittingChanges" LoadedData="SQLDomainDataContext_LoadedData">
<ria:DomainDataSource.SortDescriptors>
<ria:SortDescriptor Direction="Descending" PropertyPath="BaseProperties.CreatedOn" />
</ria:DomainDataSource.SortDescriptors>
</ria:DomainDataSource>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<sdk:DataGrid Grid.Row="0" AutoGenerateColumns="True" Name="dataGrid" ItemsSource="{Binding}" DataContext="{Binding Path=Data, Mode=TwoWay}" IsReadOnly="True" AutoGeneratingColumn="dataGrid_AutoGeneratingColumn" SelectionChanged="dataGrid_SelectionChanged" />
<custCont:LocalizedDataPager Grid.Row="1" x:Name="pager" Source="{Binding Path=Data}" PageSize="15" DisplayMode="FirstLastPreviousNext" />
</Grid>
<Border Grid.Row="1">
<Border.Background>
<LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
<GradientStop Color="#FF9D9D9D" Offset="0" />
<GradientStop Color="#FFDBDBDB" Offset="1" />
</LinearGradientBrush>
</Border.Background>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<Ellipse Fill="Black" HorizontalAlignment="Center" Width="4" Height="4" Margin="8,0"/>
<Ellipse Fill="Black" HorizontalAlignment="Center" Width="4" Height="4" Margin="8,0"/>
<Ellipse Fill="Black" HorizontalAlignment="Center" Width="4" Height="4" Margin="8,0"/>
</StackPanel>
</Border>
<sdk:GridSplitter Grid.Row="1" HorizontalAlignment="Stretch" Background="Transparent" Opacity="0"/>
<data:DataForm Grid.Row="2" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Name="DF" AutoCommit="False"
DataContext="{Binding Path=Data, Mode=TwoWay}" ItemsSource="{Binding}"
AutoGeneratingField="DF_AutoGeneratingField" EditEnded="DF_EditEnded" DeletingItem="DF_DeletingItem" Style="{StaticResource DataFormStyle}"/>
<Grid Grid.Row="3">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition />
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Button Grid.Column="0" Name="btnHideDF" Content="{Binding Source={StaticResource ApplicationResources}, Path=ApplicationStrings.ShowEntities_HideDfBtn}" MinWidth="10" Margin="2" Click="btnHideDF_Click" />
<Button Grid.Column="2" Name="bRefresh" Content="{Binding Source={StaticResource ApplicationResources}, Path=ApplicationStrings.ShowEntities_RefreshBtn}" MinWidth="75" Margin="2" Click="bRefresh_Click" IsEnabled="{Binding Path=CanLoad}" />
<Button Grid.Column="3" Name="btnCacnelChanges" Content="{Binding Source={StaticResource ApplicationResources}, Path=ApplicationStrings.ShowEntities_CancelChangesBtn}" Margin="2" IsEnabled="{Binding Path=HasChanges}" Click="btnCacnelChanges_Click" Visibility="Collapsed" />
<Button Grid.Column="4" Name="bSubmit" Content="{Binding Source={StaticResource ApplicationResources}, Path=ApplicationStrings.ShowEntities_SubmitBtn}" MinWidth="75" Margin="2" IsEnabled="{Binding Path=HasChanges}" Click="bSubmit_Click" />
</Grid>
</Grid>
When the view is displayed in a singular Frame, all is well. But when it is displayed on a page with TWO frames, odd things begin to happen. If the user grabs the splitter and moves it all the way to the top, beyond the frames boundaries, the DataForm will expand endlessly. This isn't a big issue, but it looks ugly, and makes the buttons at the bottom vanish from sight.
What's going on here? Why is this happening? How can I prevent this behaviour?
Apparently my Google-fu was weak.
I found this today, and it describes the exact same problem I had, as well as a possible solution.
Still, I didn't expect this to be a bug in SL...