I'm looking for opinion on using Canvas vs. Grid panels in WPF. I need to make classic input forms that have basically grid layouts, some may have small datagrids inside, groupboxes, but all aligned in grid layout. I’m struggling whether to use Grid or Canvas panel for all my forms. Grid is giving me good structure; I can maintain alignment of controls more easily¬. I will have base class (that inherits Window class) for all windows, so designer in Visual Studio will be useless, since it has issues for this sort of inheriting, and with Grid panel I don’t really even need designer, and I can set window SizeToContent so everything will fit just fine. But again with Canvas, I have ability to position controls any way I like, and this is only benefit I see when using Canvas.
I didn’t have that much of experience in WPF to predict on what sorts of problems could I get from customer requests on layout. On web forms I sometimes use absolute positioning for forms just in case customer has some “special” request whether to have control pixel right or left on higher etc. everyone worked with demanding customers know what I mean.
I’d like to see what you think, what are pros and cons for both in business application form layout building? Why is one better than the other? Any cases where one panel would be bad to use, and other not? What are disadvantages of one panel to another? What panel would you use ?
Thanks
Canvas is mostly intended for custom drawing functionality more than anything else. The grid is definitely the best choice available for customizing your layout.
I would go with a Grid or a specialized Grid subclass. You are right about View inheritance. The Visual Studio designer in UWP, WPF generates support code for the base and subclass with the same method names. It doesn't compile.
Since I pre-date generics we can go back to previous methodologies. One of these is a helper class. Each View implements
IBaseView
and has a propertyViewHelper
orViewHelper<T>
.enum ViewHelperOptions
may well be needed. If required, each of the ViewHelpers can use inheritance without breaking Visual Designer. This allows the use of generic code as well as specific view code without breaking the MVVM model. Let's call it MVHVM as the ViewHelper has knowledge of the ViewHelper. This further separates the V from the VM.The full implementation may well require the use of
Activator.CreateInstance
. Another consideration is the Constructors which are invoked by the designer. You have to move all the "will-crash-if-not-running" code into an Initialization spawned from (say) the Loaded event. Alternatively you can make use of (UWP):Definitely Grids seem to be what you need for your requirements.
I would liken Grids to tables in html (very useful when used appropriately), whilst Canvas is more like a div. The difference being that Grids are what tables should be in HTML and likewise with div's vs Canvas.
On the topic of grids, take the time to define your RowDefinitions and ColumnDefinitions, rather than putting margin's on your controls to position everything correctly. You'll regret it if you don't.
Even though you cannot use VS Designer, you could still use a XAML visual designer to create/edit your grid content.
One of the primary UX benefits of WPF/SL/XAML is the HTML-like 'liquid' layout capability. Even though you may not need it with your current design, it is clearly the future and well worth learning how to finesse.
Check Rob Relyea's excellent list of available XAML editors
You can get pretty in depth with the actual layout of the grid, column/row spanning, width, height, etc.
In my opinion is would be easier to do the layout of the various items on a grid by controlling the row and column sizez than do do everything hard coded into a canvas. It will also make things easier if they decide to change resolutions later on down the road.
From Adam Nathan's WPF Unleashed (p. 168):
You can also get creative with the content of your controls in the grid to have a finer level of layout control.
A canvas would be good for something like a dialog box that will rarely change size, and only has a few controls on it, because it would get time consuming to lay them all out as the number grows.
I personally use grids myself. It can be a little more work to lay things out to the pixel level but for the 5% of the time that is necessary it is worth it for abstracting away a lot of the hassle. It is also nice when there is a need to resize rows and columns on the fly, the GridSplitter makes that a snap.