Grid and StackPanel, which has the better performance? - wpf

Let's read these codes, I've defined two similar UserControls in a Windows Phone 8 project and I really want to which of them is better. I've check the profiling, it seems they are almost the same.
UserControl 1, using grid's property to design my layout.
<Grid x:Name="LayoutRoot" Background="{StaticResource PhoneChromeBrush}" Height="108">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Rectangle Grid.RowSpan="2" Grid.Row="0" Height="108" Width="54" Fill="Blue"></Rectangle>
<TextBlock Grid.Row="0" Grid.Column="1" Text="Caption" Style="{StaticResource PhoneTextExtraLargeStyle}"></TextBlock>
<TextBlock Grid.Row="1" Grid.Column="1" Text="URLURLURLURLURLURL" Style="{StaticResource PhoneTextSmallStyle}"></TextBlock>
</Grid>
UserControl 2, using StackPanel to design my layout.
<Grid x:Name="LayoutRoot" Background="{StaticResource PhoneChromeBrush}" Height="108">
<StackPanel Orientation="Horizontal">
<Rectangle Height="108" Width="54" Fill="Red"></Rectangle>
<StackPanel Orientation="Vertical">
<TextBlock Text="Caption" Style="{StaticResource PhoneTextExtraLargeStyle}"></TextBlock>
<TextBlock Text="URLURLURLURLURLURL" Style="{StaticResource PhoneTextSmallStyle}"></TextBlock>
</StackPanel>
</StackPanel>
</Grid>
It looks like the basic layout is the same. But when I use XAML Spy to analyse the Visualizing tree, UserControl 1 has less nodes, but it costs a little more memory. Why?

You may be interested in the answers to this question: In what order are Panels the most efficient in terms of render time and performance?
The short answer is it depends on how many children the panels have, and how those elements are sized and positioned. But in most cases, a StackPanel will be more efficient than a Grid as it has both a faster measure and arrangement pass.
To quote from the accepted answer:
Grid
Defines a flexible grid area that consists of columns and rows.
This can be the most performance intensive panel if proportional
sizing or auto sizing is used. Calculating child item size can be a
complex combination of the native size of the item and the layout
specified by the grid. Layout is also the most complicated of all the
panels. Slow to medium performance for the measure pass and slow to
medium performance for the arrangement pass.
StackPanel
Arranges child elements into a single line that can be oriented horizontally or vertically.
The StackPanel measures its children using either native or relative
sizing in the opposite direction from its orientation and native
sizing in the direction of its orientation (alignment does nothing in
this direction). This makes it a mid-level performer in this area. The
Arrangement pass is simply, just laying out the items in order.
Probably the second-best performance for this pass. Medium performance
for the measure pass and fast performance for the layout pass.
Also in regards to memory consumption, both objects are different and take up different amounts of memory, and a Grid has RowDefinitions and ColumnDefinitions, so it actually contains more objects than your StackPanel

Related

WPF different screen resolution settings?

Been looking around on the internet and I think more people talk about docking images etc... to the screen. What I am looking for is that I want the images and everything else on the page to stretch or shrink depending on the persons resolution?
I Havant set my screen to a height or width, I just set the screen to maximise on page load but this doesn't seem to work?
Does anyone have a solutions on this i am using a WPF Application.
You can put all your controls below the Window in a ViewBox. That will scale your whole window content.
While the ViewBox control is good for resizing UI elements, there is a preferable way to achieve the same goal. UIs in WPF are generally created using Grid controls. These enable developers to take advantage of the resizing abilities that they provide. Virtually all 'fit to size' applications use Grid elements.
When using Grid elements with the objective of filling all of the available space, there are a few things that you should consider. You generally shouldn't use exact widths and/or heights, instead using the "Auto" setting. Also, you must have at least one column and/or width dimension set to "*"... this will take up all of the remaining space:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="Top left" Background="LightSeaGreen" Padding="20" />
<TextBlock Grid.Row="1" Grid.Column="0" Text="Bottom left" Background="LightBlue" Padding="20" />
<TextBlock Grid.Row="0" Grid.Column="1" Text="Top right" Background="LightGreen" Padding="20" />
<TextBlock Grid.Row="1" Grid.Column="1" Text="Bottom left" Background="LightCoral" Padding="20" />
</Grid>

ListBox in WPF page looks fine on my PC, but the data shrinks on smaller resolutions

I've tried almost every combination of alignments and margins, to no success. The ListBox is on a WPF page, which is bound to a frame on the main window.
The ListBox itself is fine. It aligns just as I expect it would. My ListBoxItem contains an Image and a TextBlock. The TextBlock gets cut off.
As you can see from the following image, things are mostly good.
The ListBox is appropriately offset from the left edge and the top of that blue box. The content Image and TextBlock are fairly centered and so is the ListBoxItem outline. This is on my development machine.
I thought the whole reason for using grids, grid lines, and alignment properties, was so we didn't have to set a hard coded size. That our controls would resize themselves. Which does actually work just fine for everything else.
But when I place this on a small screen, I get this:
The ListBox itself is still aligned correctly. But now the ListBoxItem is forced down. It's top alignment is still good, but the bottom is pushed down so we can't see the TextBlock or the bottom of the ListBoxItem.
Here's my XAML:
<Grid VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Margin="1">
<Grid.RowDefinitions>
<RowDefinition Height="292*" />
<RowDefinition Height="30*"/>
</Grid.RowDefinitions>
<ListBox Grid.Row="1" Name="lbButtons" Margin="2,0,0,1.5" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Visibility="Visible" >
<StackPanel Name="spListBoxItems" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Orientation="Horizontal">
<ListBoxItem Margin="0,0,0,0" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" >
<StackPanel Orientation="Vertical" HorizontalAlignment="Center" Margin="10,5,10,5">
<Image Source="/COBAN.CobanConsole.UI;component/Images/Buttons/Light/record48_light.png" />
<TextBlock Text="Record" Margin="5,5,0,0"></TextBlock>
</StackPanel>
</ListBoxItem>
</StackPanel>
</ListBox>
</Grid>
Not much to it. Any ideas on what's going on?
You're using * units on your grid row definitions. Those are relative measures: they just tell you what proportion of the space the rows can take up. If you need your listbox to have a specific height, you should change your second row to have an absolute size instead, like this:
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="30"/>
</Grid.RowDefinitions>

Setting width in a data template based on the size of a parent control

I am using a telerik TreeView in WPF, and I'm using a HierarchicalDataTemplate to show the nodes. Nodes represent matched items - which can be left only, right only, equal or inequal (a tree based comparison).
I am currently using a DataTemplateSelector to select from one of four templates, which all look similar to the following:
<HierarchicalDataTemplate x:Key="EqualTreeItemTemplate" ItemsSource="{Binding}">
<Grid Name="rowGrid" HorizontalAlignment="Stretch" Height="Auto" d:DataContext="{d:DesignInstance Carbon:ICarbonComparisonPair }">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="16" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Path Data="F1M574.042,314.611L533.8,344.398 522.251,328.798 515.235,333.988 526.786,349.593 526.782,349.596 531.978,356.603 579.235,321.622 574.042,314.611z" Stretch="Uniform" Fill="#FF000000" Width="16" Height="16" VerticalAlignment="Center" Margin="0,0,0,0" />
<TextBlock Grid.Column="1" Text="{Binding ObjectName}" Style="{StaticResource ObjectNameStyle}" Margin="4,0,0,0" />
<TextBlock Grid.Column="2" Text="{Binding ObjectName}" Style="{StaticResource ObjectNameStyle}" Margin="4,0,0,0" />
</Grid>
</HierarchicalDataTemplate>
The problem that I have is that the item content area is a different width based on the level of the tree that the item appears in. This means that the columns that I have don't line up - the text in the right hand column shifts to the right a bit for each level of the tree that you expand.
What I would like to do is specify the right hand grid column's width to be 50% of the size of the tree control as a whole, rather than 50% of the grid's natural area. I thought maybe I could do this with a binding with a RelativeSource, but I just can't seem to make it work. Is there a way to achieve this in XAML, or do I need to resort to code-behind?
If I'm understanding it correctly you want column index 2 to align across all items?
Check out the TreeListView control and see if that gives you what you need.
Silverlight demo here (just so you can see what it looks like - the WPF version is pretty much the same)
[Edit - More info]
The SharedGroupName property on ColumnDefinition is tempting but, thanks to the indent, it won't quite work - you'll end up with all of the content in column 1 or 2 being sized the same, but the pesky indent still throws it off. Check out ListView's View Property. I'm believe it's at least in the same spirit as what Telerik TreeListView is, if not darned similar in implementation.
Here's a decent writeup on how to use it. (Ironically I have that page bookmarked in a folder called "TreeGridList" so apparently at some point I had the idea to do that to accomplish something similar :) )

Recreating WinForms layout in WPF

I've just inherited an old WinForms app with a UI layout like this:
I'm tasked with updating several things about the software one of which is porting it to WPF which I've not previously worked with. I'm also told that the new WPF UI must look identical to the existing UI layout so I'm trying to figure out how to create that layout in WPF. I need a toolbar across the top of the window which stretches the entire width of the fixed-size window. Can I do that in the default grid or do I need a dockpanel to do that? Also, I'm assuming that I would use a grid with 2 columns and 3 rows to layout the six groupboxes?
Anything you can do with a DockPanel can also be done with a Grid -- the DockPanel is just a shortcut. So yes, you can do all this with the default Grid.
As for how to do the layout: it depends on how you want things to resize. Does everything stay proportional when you resize? If so, a single Grid with three columns (and percentage sizes for the ColumnDefinitions) would be fine. You would actually need four rows, though, not three -- the first RowDefinition would be for the ToolBar (using ColumnSpan="3") and would need Height="Auto" so it uses the ToolBar's default size; the remaining rows would be percentage-sized.
Try that, see if it works for you. If the resizing needs to be more complicated than just proportional, then post a second screenshot of the window at a different size, and we could try to help you further.
Personally I would use a DockPanel for the Menu/Content areas, then use a Grid in the Content Area to define the GroupBoxes
<DockPanel>
<Grid x:Name="MenuRegion" DockPanel.Dock="Top" />
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
</Grid>
<Grid Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" />
<Grid Grid.Row="0" Grid.Column="2" />
<Grid Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" />
<Grid Grid.Row="1" Grid.Column="2" />
<Grid Grid.Row="2" Grid.Column="0" />
<Grid Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2" />
</DockPanel>
Of course, you could also make the Menu area part of the Grid and set it to span all rows, but I personally like keeping them separate.
Grid with 3 row (one for the menu). Since you have uneven spacing in the rows just a single column on the main grid. Then grid in the grid for the two column spacings.

Silverlight 4 - ScrollViewer and child DataGrid MinHeight

edit: I'm rewriting almost the entire question because I realized the question was incorrect and confusing. I apologize for this, but the question had incorrect assumptions that made it impossible to answer. I originally tried to simplify it to make it easier to understand, but this made it impossible to replicate my problem.
If I have an DataGrid with a MinHeight in a ScrollViewer, I would expect that as my ViewPort shrinks, the ActualHeight of the element would be decreased until it hits MinHeight before the scrollbars show up.
Instead, it seems that when the datagrid's rows cumulative heights add up to more than the MinHeight, this value overrides MinHeight
Is there a way to do this without manually sizing everything and having a ton of code?
Example:
<ScrollViewer VerticalScrollBarVisibility="Auto" Background="Red">
<Grid x:Name="LayoutRoot" Background="Black" HorizontalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition MinHeight="20"/>
<RowDefinition Height="80"/>
</Grid.RowDefinitions>
<sdk:DataGrid AutoGenerateColumns="True" Name="dataGrid1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" MinHeight="20" />
<Rectangle Fill="Blue" Width="100" Height="80" Grid.Row="1" />
</Grid>
</ScrollViewer>
If you were to populate this grid with some rows, if you maximize the window, the grid takes up most of the space and has white space after the rows. If you shrink it down, the layout takes away from the white space until that space runs out, then the root level ScrollViewer kicks in, even though MinHeight has not been reached.
If you replace the DataGrid with another rectangle, the behavior is different (obviously). The new rectangle would shrink down to height 20.
How do I achieve this with the grid? My requirements are to have nested scrollbars on my SL page (which I find distasteful, but it's not in my control). The idea is that the top level scrollbars are a "last resort" of sorts.
What about this:
<ScrollViewer>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="250" />
</Grid.RowDefinitions>
<Rectangle MinHeight="150" Background="Red" Grid.Row="0" />
<Rectangle Height="250" Background="Blue" Grid.Row="1" />
</Grid>
You did not have the Grid.Row values set on either of the rectangles.
You've not provided sufficient information to solve your specific problem. However, it is easy to demonstrate that the ScrollViewer does work in exactly the fashion you desire by distilling down to something as simple as:
<UserControl ...>
<ScrollViewer VerticalScrollBarVisibility="Auto">
<Border MinHeight="200" BorderBrush="Blue" BorderThickness="1" Background="Red"/>
</ScrollViewer>
</UserControl>
Put this in a standalone Silverlight application in the main page and you'll see that the ScrollViewer only displays the vertical scroll bar when the window is small enough. You can download the solution here.
This is because ScrollViewer itself has a border and padding that occupies little space of its own. Try considering little extra height that should match space of scrollbar border.
Another option will be to change the control template of scrollviewer and remove the border and extra space occupied around content presenter. And set horizontal scroll visibility to collapsed so it will not occupy space.

Resources