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.
Related
I need a control where user can pick only one option. Combobox is fine, radiobuttons are ok, but for some purpose I think about another crazy, but interesting solution.
There should be a slider control on a window and three possible positions of this sliding thing. I know this can be easily accomplished by setting slider's Minimum and Maximum plus TickFrequency and IsSnapToTickEnabled properties.
Now, is there a way how to add labels on left/right edge and center of slider showing user options within the slider? Or is it neccessary place labels/textblock below?
Last, though the most important thing is, how to associate integer slider positions with string options? I thought about switch, but this is wpf - there is "more wpf" solution, isn't it?
Just drag slider's rider to it's position and by binding set class string property to appropriate value.
Every control within WPF can have its visuals completely modified to suit your needs. This was/is the beauty of WPF over WinForms.
Can your slider have a TextBlock within it? Absolutely. Style as you desire and be on your way. A great article can be found via MSDN Magazine which outlines the approach to customizing WPF controls.
With regard to the integer values, use an IVauleConverter to translate the values to whatever you prefer.
I've written a WPF control which accepts a number of UIElement objects as input and displays them docked either vertically or horizontally. The control exposes functions for enumerating, removing and inserting children, but internally I'm using a Grid to build the layout, creating a row/column for each item and inserting a GridSplitter between them. To do this I've inherited from ContentControl, and upon initialization I just set the Content property with the Grid. Everything is working as intended, but now I wonder if this might be confusing for the user of my control, as it would be counter-intuitive to have a ContentControl that has many items.
Should I be inheriting from ItemsControl instead?
Should I inherit directly from Control which is "content-agnostic"?
Is there a better way to do this?
Thanks in advance.
What you describe sounds like a Panel - basically a control which is responsible for the layout of many elements. I would consider inheriting from that.
Your mention of "docked either vertically or horizontally" leads me to believe perhaps a StackPanel would be a better fit, since it does docking as well.
I'd like to know what the differences between an Style (for a control) and a control template are.
Best regards,
Gonzalo
A style controls the individual properties of a control. For instance, a button style can say, "For every button, use this background." A style is changing a single property on a control.
A control template is actually handling how the control displays its bound data. Instead of saying, "I want to override a control's properties," you are assembling together other smaller controls into a single control that can present different views of the bound data.
Previously in WinForms, if you wanted to write a custom list box (say that had an icon next to each item), you had to inherit from the ListView control and override the painting methods. This involved a ton of experimentation - huge pain. With WPF templates, you can use XAML to construct smaller controls together and bind them to different properties of the parent control. You are actually defining the Visual Tree for the control.
See this article for an in-depth explanation by Charles Petzold.
Imagine your control is a house.
A Style is conceptually similar to putting down a new carpet and painting the walls. The house itself is still the same but its outward appearance is different.
A ControlTemplate is the equivalent of knocking down a wall or adding a conservatory. The actual structure of the house has changed.
Use a Style when you want to change the outward appearance of the control E.G. it's background colour or the thickness of it's border.
Use a ControlTemplate when you need to change the underlying structure of the control. This is useful when you want to change the layout of certain aspects of a control. A good example is in this article which re-templates a TabControl to look like the navigator from Microsoft Outlook.
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
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).