WPF: Why all the love for the Grid control? - wpf

Seen various examples of WPF applications I've seen the use of the Grid control for almost anything, even simplest things with only 1 column or row.
Also, the WPF templates start with an empty grid.
For me, using StackPanel or DockPanel is less verbose and are better for maintenance (think adding a row later and having to add +1 to all the other rows)
Why is Grid better or what I am missing?

Two words: Star sizing. The Grid makes it possible to size content to the space that contains it without explicitly providing a size for the container. The panel controls don't.

I think part of the reason for Grid being the default element is that it's (slightly) more designer-friendly.
With a Grid, there is no restriction on having multiple elements within a single Grid "cell", which allows a designer with free placement to have the same flexibility as a Canvas, but still have the automatic layout capabilities that Grid (and the other nicer layout controls like StackPanel and DockPanel) contains.

not missing anything. I have quite a lot of grids in my application(s), but not necessarily as top level element and definitely not to the extend you describe.
Could be many people just dont realize that they can remove the initial grid, and instead they put their own control into the grid.

I have found that for more elaborate windows, it is easier to break it down into functional areas that are fairly independent (movement and size wise) of the others. Grids allow those areas to coexist in a single panel, and allow them to be positioned without regard for where other controls are (to some extent).
For instance in a project I am working on right now, I have a window that is going to be a shipping manager. I want three list views (Shipments, Packages, Items) I have a grid control with two columns; one with the Packages list and a grid splitter, the other with a nested grid with the other two lists and a grid splitter.
i have seen many designers break their window down into areas like this, and doing it with anything other than a grid just doesn't work since there are no discreet "cells" that items indirectly live in. Quite a few program windows take this design and so I guess when they had a meeting and asked what should be the default container panel, grid was the choice based on that fact.
Cory

Related

Using the DragDropTarget with a traditional Grid

Silverlight 4 now provides controls to handle Drag and Drop actions. All the Target Controls seem to inherit from DragDropTarget Like so
public class MyControlDragDropTarget : DragDropTarget<TItemsControlType,TItemsContainerType>
.
.
.
A number of controls have pre-defined DragDropTargets including the DataGrid, ListBox, Panels
Which is all very well, but I want to drag and drop from a grid not a datagrid, and there is no pre-defined one for a normal grid.
I actually want to drag a given row from the grid, but without a Container Type for a Grid I cannot work out how to define a DragDropTarget control for the grid.
Only way I can think is instead of using a grid - I use a listbox (for which there is a DragDropTarget) and then place a StackPanel or Grid in each row (which has one row of 'n' columns)
Anyone got any ideas
Ta in advance
A "normal grid" is simply another form of panel, there is no need for specialised DragDropTarget for the Grid, the existing PanelDragDropTarget is sufficient for a "normal grid".
Its important grasp that the Grid does not support the concept of "rows containing cells containing UI elements". The rows and columns of a Grid are entirely equal and are defined purely for layout purposes. UIElement children of a Grid are laid out entirely independently of each other, there is no concept of a set of values belonging to either a column or a row that can be moved or operated on as a group (like picking up a row and dragging it).
Sounds like you have already got an answer for yourself, use the ListBox instead.
BTW, DragDropTarget isn't provided by Silverlight 4 but rather the Silverlight Toolkit. This is an important distinction because the current quality band assigned to DragDropTarget is "Experimental". You need to think carefully about this if you want to use such code in some production release of your own.

How does one gauge/know the weight of an element?

I'm working on the UI side of a WPF project. My favourite reference while XAML'ing at the moment is Adam Nathan's "Windows Presentation Foundation Unleashed". He gives the following tip regarding control templates: "Rather than using a ContentControl inside a control template, you should use the lighter-weight ContentPresenter element".
The developers I work with will often also tell me to use the most lightweight elements I possibly can in all of the XAML'ing I do - which I totally understand.
How do I find out what the relative "weights" of different elements are? There are obvious things, like a RichTextBox versus a TextBox. But how do I figure out, for instance, whether a StackPanel is better than a Grid in a situation where either can do the job?
Is an element/control's visual tree a good indicator of "weight"? What else can I look at?
When it comes to things like ContentPresenter vs. ContentControl, you can check the inheritance hierarchy: ContentPresenter derives from FrameworkElement whereas ContentControl derives from Control.
As far as panels go, basically Grid has the most complex layout logic (which is why it is the most flexible), so generally any other panel is going to be better if it can get the job done. If you want a concrete guide to panel complexity, I would list them in the following order from least to most complex:
UniformGrid - The child size isn't even used to calculate the panel's extent
StackPanel - Only one dimension of the child's size is used
WrapPanel - Similar to StackPanel, but a little more complex as the widest element of a column/row have to be remembered.
DockPanel - Since only one element can take up all remaining space, I'd say it is lighter weight than Grid.
Grid - The most flexible, and therefore has the most complex layout algorithm.

WPF Grid of Images - Best control to use?

I'm trying to convert my VB project to WPF, and one big problem I'm having is what to do about a large GridView that contains in each cell a single image. The grid needs to be very large so is the best way to do this in WPF a datagrid, or a dynamically generated Grid control, or something else? I'm not sure which controls give the best performance as the grid could be 100 x 100 or more.
Any suggestions would be brilliant :o)
I would try using the WrapPanel, to allow for items to flow nicely.
If the images are not of the same size though, you could try the UniformGrid within a ScrollViewer, as it will align items for you uniformly.
Performance wise, I'd say don't optimize prematurely! When you have a nice User Experience, you need to do some reading and decide for yourself. Have a look here.

WPF column resize performance issues

Are there in general any known performance issues in WPF related to grid column resizing?
I have an application where I need to do some particular things in a column, but for all the different solutions I find the column resizing gets slow. This applies when I have typically more than 1000 elements in my list, but I assume this isn't too much for WPF..? So; the general question is whether you've experienced slow column resizing, and whether you've found solutions for this? What was causing it?
Some more details about my particular case:
I can have two different things in my columns; ComboBox or TextBlock. The ComboBox should fill the whole column and follow on column resize, and clicking an empty area of a column with a TextBlock should select the row. This is where the problem is. For all solutions I have to this the column resizing gets slow. The only way to make resizing smooth that I've found is by adding a StackPanel outside them with Orientation="Horizontal", but with this I'm unable to achieve the styles described above.
Here are some observations:
Adding style HorizontalContentAlignment="Stretch" to the items of the list makes the ComboBoxes stretch and the TextBlocks clickable, but also column resize slow.
Adding Background="Transparent" to either the StackPanel or the elements that are inserted inside them solves the problem too, but makes resizing slow.
Adding an outer StackPanel with property Orientation="Horizontal" makes resizing smooth, but I'm unable to apply the styles as described.
Have you tried virtualizing the elements in the ListView? When you are virtualizing, the virtualizing panel only creates the visuals for the elements that are in the view. This allows you to have large numbers of items without performance issues like you mention. See VirtualizingStackPanel for more details. Also The Layout System. You can create your own virtualizing panels. If you look up "virtualizing+wpf" on google you'll find lots of hits for virtualizing Canvases, WrapPanels, and etc.
I hope this helps.

Can I make WPF grid controls opaque at design time?

So I'm just starting out with WPF, and I'm really annoyed by the fact that if I lay two Grids on top of one another, the top Grid isn't opaque. It makes designing extremely annoying. Can this be turned off somehow?
I'm just building your standard Winforms STYLE application, but in WPF. I'm just trying to start bridging the gap here. In Winforms(and VB) you'd always have group boxes or something on your form, and then depending on some user context, one of those group boxes would be on top. Its how I've designed forms since time immemorial. One of two things must be true here:
A) This is not the recommended way to design Windows going forward with WPF, but I don't understand what you're supposed to do
B) There is some property to make the Grids opaque so I can build the Window in the style that I'm used to.
I'm fine with answers that solve either A or B. If I'm not doing things the right way because they've changed, then please enlighten me.
Update: So it turns out, I can make the grid opque by setting the background color, but now it seems like I'm locked into a White background as opposed to sticking with the system colors.
You could use SystemColors to make the control background colour match (rather than being white).
I don't understand why you want to put one grid on top of another though. In WPF you generally use a single grid to stack multiple visual elements within one region. Can you explain why you want to hide things in the background with foreground elements?
It sounds a little like you're implementing a tab control -- switching between pages of controls depending on focus. Have you experimented with the new TabControl?
I'm moving from WinForms to WPF development wherever possible and have found that in doing so it's taken some readjustment. WPF has a completely different way of laying things out and now that I'm more comfortable with it, I think it's superior. I'm guessing you just need to ride the learning curve a little longer.
Hope that helps.
EDIT: In response to your comment, I imagine you can have a tab control without tabs, though I haven't tried it myself (might be worthy of another question on SO). Tab controls are headered controls, meaning that they have a header item and a content item. In this case, the header is the tab button, the content is the page item. You can specify a ControlTemplate that details how these items should be displayed relative to one another.
Interestingly, many other types of common GUI element are also headered controls:
Menu items - The menu item text/icon is the header, and the optional submenu is the content
Tree view - Each node is the header, and optional children are within the content
Group box - The header is, well, the header and the content is, well, the content :)
Note that in the case of menu items and tree views, the type may recursively nest within itself. This is quite elegant and can give some wildly different presentation options over the same logical model with only changes to the control template.
For more information read about HeaderedContentControl and HeaderedItemsControl
You could use the following:
<Grid Background="{DynamicResource {x:Static SystemColors.WindowBrush}}">
<!-- content -->
</Grid>
This will respond to changes in the system colors on the fly (the DynamicResource does this).

Resources