Grid vs. Canvas

2020-06-09 07:52发布

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

5条回答
劫难
2楼-- · 2020-06-09 08:20

Canvas is mostly intended for custom drawing functionality more than anything else. The grid is definitely the best choice available for customizing your layout.

查看更多
狗以群分
3楼-- · 2020-06-09 08:22

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 property ViewHelper or ViewHelper<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):

if (!Windows.ApplicationModel.DesignMode.DesignModeEnabled)
{ DoStuffWhichShouldOnlyBeDoneAtRunTime(); }
查看更多
我想做一个坏孩纸
4楼-- · 2020-06-09 08:35

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.

查看更多
SAY GOODBYE
5楼-- · 2020-06-09 08:40

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

查看更多
看我几分像从前
6楼-- · 2020-06-09 08:44

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):

Mimicking a Canvas with Grid If you leave Grid with a single row and column and set the HorizontalAlignment and VerticalAlignment of all children to values other than Stretch, the children get added to the single cell just like a Canvas. Setting HorizontalAlignment to Left and VerticalAlignment to Top is like setting Canvas.Left and Canvas.Top to 0. Setting HorizontalAlignment to Right and VerticalAlignment to Bottom is like setting Canvas.Right and Canvas.Bottom to 0. Furthermore, applying Margin values to each element can give you the same effect as setting Canvas’s attached properties to the same values.

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.

查看更多
登录 后发表回答