More on WPF Controls
If you recall, the Button that we have placed in the top left of the Grid (Column 0, Row 0) is configured to automatically resize itself as the Window is resized. Once you get past the first flush of pleasure at this handy and easy to implement facility, you'll probably come to realise that sometimes we don't want controls to expand beyond a certain size. In some cases, if a button for example becomes too big it somehow just doesn't look right. And of course there will always be situations where we don't want it to reduce to such a small size that it is hard to use or that its content is difficult to view.
We'll deal with that next, but as I mentioned the word "Content" just now, we should look at another change from WinForms to WPF.
Most controls have a Content Property. In the majority of cases this is text. Therefore the equivalent of the WinForms Button's Text Property is the WPF Button's Content Property. Not great problems there; just a change of name.
When you are using other people's samples though you may well find snippets where what is obviously the text (that is, the Content) for a Button simply appears as text literals somewhere inside the Button's opening and closing tags. This is because by default any text you enter in the Button's tags that isn't assigned to a specific property will be assumed to be Button Content. In other words, in VB.NET terms, it's the default property of the control. So just bear that in mind when you start seeing strange error messages (as I'm sure you will sooner or later) or if the text that appears on a control looks spookily like the code you are trying to apply to a control's properties!
So, to give our first button control some Content, simply type in the text you want to see displayed on the button, placing it between the:
<Button Name="GoButton"> and
You can see this in the first screenshot of the next section.
Constraining a Control's Size
The XAML code for this is uncomplicated. Set any of the size constraints with code such as shown in the following example:-
MinHeight and MinWidth properties are also available for setting when you need them. If you run the project now and increase the size of the Window you will see that the button expands only until it reaches the set limit. Once it has reached that limit however it still continues to adjust its relative position within the grid and the window.
You will see that the code block shown in the screenshot also includes the Content, and I have turned off the code that shows the gridlines.
You probably also noticed the layout of the XAML has been broken up into separate lines for logical groups. This isn't necessary and you can put all the code on one continuous line if you prefer. For clarity, I'll continue to use the separate lines. There's no performance penalty - white space comes for free in XAML!
Positioning Controls inside a Grid
We'll add a second control to this grid, but this time we will use more of the Visual Studio facilities and less hand coded XAML.
Click on the Grid in the Design Pane (or click on the word "Grid" in the XAML Pane, as this will automatically move you to the Design Pane). Now go to the Toolbox. From the Common Controls Tab select a Label control. Drag it from the Toolbox and drop it in the middle cell of the right hand column of the Grid.
Now take a look at the XAML Pane and see what has been inserted there for you. By default, any properties that have been set for you are all on one line, as mentioned earlier. In the screenshot below I have inserted carriage returns to make it easier to view:
Some of these need more explanation.
Some Basic Properties
The first two properties displayed obviously define which grid cell in which this label should be placed. (Recall that Columns and Rows are zero based - the button is in (0,0), so this label is in (1, 1)). What may be less obvious is how the column and row values are described.
The "Grid.Column" and "Grid.Row" properties shown there are known as Attached Properties. Briefly, an attached property is a property which refers to another class. So in this simple example the class being referred to is the Grid. The label doesn't understand Columns and Rows, but of course the grid does. This code instructs the label to be placed in Column 1 and Row 1 of the containing grid.
The key point to note is that you have to use the dot notation as seen in the screenshot. If you try and simply type Row="1" then this will not have the effect you want. Attached Properties are widely used in WPF and we will look at them in more detail later.
The HorizontalAlignment property is set to "Left". This is similar to the Anchor property in WinForms.
Those excruciatingly detailed Margin properties aren't as scary as they first seem. (Your values will almost certainly be slightly different than mine, depending on where you have dragged the label to at the point where you drop it in the cell.) The Margins are recalculated as you drag the label around inside the grid cell. Alternatively you can type in any hard coded values you want. The order of the settings are: Left, Top, Right, Bottom. Be aware that there is also a Padding property which is often more useful when you are trying to control detailed positioning of controls. But for now we'll just play with the hand we're dealt!
There are further options for the Margin settings (and everything else!). The one I'll mention here is that if you assign a single value - that is, one value, not a type "Single"!) then this value is applied to all four sides of the control. This can be quite useful for Margins and Padding.
By the way, it seems that if you drag the control around in the Design Pane then the XAML code reformats itself to the single line display. There may be a setting to override this; I haven't found one yet if there is. But then, there's a whole bunch of stuff I haven't found yet!
The Name Property is self-evident and basic - "Label1". The point to note here though is that this name has been assigned automatically because you created the control by dragging and dropping. (Recall that when we created the button by hand we had to assign its Name property ourselves.) If you move now to the code behind - window1.xaml.vb - and click the left hand combobox you will see that Label1 is indeed available for you to code against, should you want to.
If you decide that you absolutely won't want to code in VB against any of the events in the label then you can have it removed from the combobox's list by going back to the XAML Pane and deleting the name. I suppose if you have a huge list of controls and want to slim it down then you might do this, but it's not something I see myself doing on a regular basis.
I don't think the Width property needs any explanation, other than the obvious comment that you can change it in XAML code, or by selecting it in Design Pane and dragging its drag handles - or indeed by entering values in the Properties Window, in the way you are familiar with in VS 2005. In passing, I've got to say that I'm not thrilled with the Properties Window in WPF. I like to have my properties listed alphabetically in VS 2005. Currently WPF doesn't offer me that option.
We have previously covered the Content property; in this case it was automatically assigned a value to describe the particular control - "Label".
Another property you are quite likely to change on a control is the one we think of in VB as the BackColor property. In WPF this is the Background property. Again you can set it in the XAML Pane or in the Properties Window. If, like me, you think of your colors by the color name then you can enter any of these and it will be applied to the control.
Well. not quite true. If it recognises the color name it will make the change. If it doesn't, it will leave it at either the default color for that control or at the last color that was set that it did recognise. The color range doesn't seem to be the complete KnownColors enumeration from VB and is, I think, a list that represents colors recognised by most web browsers.
Interestingly, if you type a color name into the Properties Window it will immediately and automatically change your literal into the Hex value for that color.
If you study that screenshot carefully, you'll notice that the Background property is in fact listed under the subheading of "Brushes" in the Property Window. Under the hood, WPF uses a Brush object to color the control; the use of just the color name is an aid to make life easier for the developer. Life would be easier if a list of acceptable colors is available (as you get in VB.NET when you type "Color." . I haven't seen a way of achieving this yet, either in the XAML pane, properties window or even in the code behind. As far as I know, WPF doesn't recognise the KnownColors enumeration from WinForms.
In that previous screenshot you will also have seen that I have included BorderBrush and BorderThickness properties. A point to note is that you must include values for both of these properties if you want them to be effected.
The Foreground Property is the WPF equivalent of ForeColor and will set the color of the Font for you. The Font size can be set in XAML or in the Properties window.
You can position the Label's Content (its Text) in various ways. By far the easiest tool for doing this is the Properties Window.
There are many other properties that can be set on the label, but for now we will move on to other things. The code we have entered so far for the label - and the resulting appearance - are shown in the following screenshot:
The next task is to create a simple shape inside one of the cells - something that is very easy to do in WPF. The next part of this article can be found here.