Showing posts with label UIElement. Show all posts
Showing posts with label UIElement. Show all posts

Wednesday, March 9, 2011

Layout (Code)

Controls that derive from the ContentControl class (such as Window, Button, Label, and ToolTip) have a property named Content that you can set to almost any object. Commonly, this object is either a string or an instance of a class that derives from UIElement. The problem is you can set Content to only one object, which may be satisfactory for simple buttons, but is clearly inadequate for a window.
Fortunately, the Windows Presentation Foundation includes several classes designed specifically to alleviate this problem. These are collectively known as panels, and the art and science of putting controls and other elements on the panel is known as layout.
Panels derive from the Panel class. This partial class hierarchy shows the most important derivatives of Panel:
UIElement
    FrameworkElement
         Panel (abstract)
                Canvas
                DockPanel
                Grid
                StackPanel
                UniformGrid
                WrapPanel
The panel is a relatively recent concept in graphical windowing environments. Traditionally, a Windows program populated its windows and dialog boxes with controls by specifying their precise size and location. The Windows Presentation Foundation, however, has a strong commitment to dynamic layout (also known as automatic layout). The panels themselves are responsible for sizing and positioning elements based on different layout models. That's why a variety of classes derive from Panel: Each supports a different type of layout.
Panel defines a property named Children used to store the child elements. The Children property is an object of type UIElementCollection, which is a collection of UIElement objects. Thus, the children of a panel can be Image objects, Shape objects, TextBlock objects, and Control objects, just to mention the most popular candidates. The children of a panel can also include other panels. Just as you use a panel to host multiple elements in a window, you use a panel to host multiple elements in a button or any other ContentControl object.

Although automatic layout is a crucial feature in the Windows Presentation Foundation, you can't use it in a carefree way. Almost always, you'll have to use your own aesthetic sense in tweaking certain properties of the elements, most commonly HorizontalAligment, VerticalAlignment, Margin, and Padding.
Looking at them 1 by 1: 
StackPanel

Tuesday, March 8, 2011

Shapes in WPF (code)

Take a look at the namespace System.Windows.Shapes, which contains an abstract class named Shape and six other classes that derive from it. These classes also derive from UIElement by way of FrameworkElement:

Object
--DispatcherObject (abstract)
------DependencyObject
----------Visual (abstract)
--------------UIElement
--------------------FrameworkElement
--------------------------Shape (abstract)
--------------------------------Ellipse
--------------------------------Line
--------------------------------Path
--------------------------------Polygon
--------------------------------Polyline
--------------------------------Rectangle

While Image is the standard way to display raster images, these Shape classes implement simple two-dimensional vector graphics. Eg. lets take ellipse:

Ellipse elips = new Ellipse();
elips.Fill = Brushes.AliceBlue;
elips.StrokeThickness = 24; // 1/4 inch
elips.Stroke = new LinearGradientBrush(Colors.CadetBlue, Colors.Chocolate,
new Point (1, 0), new Point(0, 1));


Neither the Shape class nor the Ellipse class defines any properties to set a size of the ellipse, but the Ellipse class inherits Width and Height properties from FrameworkElement, and these do just fine:

elips.Width = 300;
elips.Height = 300;



Create Image from URI

Image is popular class that inherits from FrameworkElement. Here's the class hierarchy:

Object
--DispatcherObject (abstract)
----DependencyObject
------Visual (abstract)
--------UIElement
------------FrameworkElement
------------------Image

The Image class lets you easily include an image in a document or an application.

Uri uri = new Uri("http://www.images.com/bird.jpg");
BitmapImage bitmap = new BitmapImage(uri);

Image img = new Image();
img.Source = bitmap;


A couple of steps are required to display an image. The program first creates an object of Uri that indicates the location of the bitmap. This is passed to the BitmapImage constructor, which actually loads the image into memory. (Many popular formats are supported, including GIF, TIFF, JPEG, and PNG.) The Image class displays the image in the window.


You can find the Image class in the System.Windows.Controls namespace. Strictly speaking, Image is not considered a control and does not derive from the Control class. But the System.Windows.Controls namespace is so important that I'll include it in most programs from here on. The BitmapImage class is located in the System.Windows.Media.Imaging namespace, which is certainly an important namespace if you're working with bitmaps. However, I won't generally include a using directive for this namespace unless the program requires it.

Alternatively, you can load an image file from a local disk drive. You'll need a fully qualified file name as the argument in the Uri constructor, or you'll need to preface the relative file name with "file://".

Uri uri = new Uri(
System.IO.Path.Combine(
Environment.GetEnvironmentVariable("windir"),"BirdsOnComp.bmp"));




The Environment.GetEnvironmentVariable method retrieves the "windir" environment variable, which is a string like "C:\WINDOWS". The Path.Combine method combines that path name with the file name of the desired bitmap so that I (the lazy programmer) don't have to worry about inserting slashes correctly. You can either preface the Path class with System.IO (as I've done) or include a using directive for that namespace.

Rather than passing the Uri object to the BitmapImage constructor, you can set the Uri object to the UriSource property of BitmapImage. However, it's recommended that you surround the setting of this property with calls to the BeginInit and EndInit methods in BitmapImage:

bitmap.BeginInit();
bitmap.UriSource = uri;
bitmap.EndInit();


As you know, bitmaps have a pixel width and a pixel height, which is to the number of picture elements actually encoded in the file. The BitmapImage class inherits integer read-only PixelWidth and PixelHeight properties from BitmapSource that reveals this information. Bitmaps often (but not always) have embedded resolution information. Sometimes this resolution information is important (a scan of a rare postage stamp) and sometimes it's not (a photo of your postal carrier). The resolution information in dots per inch is available from the read-only double values DpiX and DpiY. The BitmapImage class also includes read-only double properties named Width and Height. These values are calculated with the following formulas:



Without the value of 96 in the numerator, these formulas would give a width and height of the image in inches. The 96 converts inches into device-independent units. The Height and Width properties constitute the metrical size of the bitmap in device-independent units. BitmapImage also inherits from BitmapSource a Format property that provides the color format of the bitmap; for those bitmaps that have a color table, the Palette property gives access to that.

The Image class does not have its own Background and Foreground properties because those properties are defined by the Control class and Image is not derived from Control. The distinction may be a little confusing at first. In earlier Windows application programming interfaces, virtually everything on the screen was considered a control. That is obviously not the case here. A control is really just another visual object, and is characterized mostly by giving feedback to user input. Elements like Image can obtain user input, of course, because all the keyboard, mouse, and stylus input events are defined by UIElement.

The concept of Content

The Window class has more than 100 public properties, and some of themsuch as the Title property that identifies the windoware quite important. But by far the most important property of Window is the Content property. 
You set the Content property of the window to the object you want in the window's client area.
You can set the Content property to a string, you can set it to a bitmap, you can set it to a drawing, and you can set it to a button, or a scrollbar, or any one of 50-odd controls supported by the Windows Presentation Foundation. 
You can set the Content property to just about anything. But there's only one little problem:
You can only set the Content property to one object.
This restriction is apt to be a bit frustrating in the early stages of working with content. Eventually, of course, you'll see how to set the Content property to an object that can play host to multiple other objects. For now, working with a single content object will keep us busy enough.


We've seen that window content can be plain text. But the purpose of the Content property is not to display simple unformatted text. No, no, no, no, no. What the Content property really wants is something more graphical in nature, and that's an instance of any class that derives from UIElement.
UIElement is an extremely important class in the Windows Presentation Foundation. This is the class that implements keyboard, mouse, and stylus handling. The UIElement class also contains an important method named OnRender. The OnRender method is invoked to obtain the graphical representation of an object.
As far as the Content property goes, the world is divided into two groups of objects: Those that derive from UIElement and those that do not. In the latter group, the object is displayed with ToString; in the former group, it's displayed with OnRender. Classes that derive from UIElement (and their instantiated objects) are often referred to collectively as elements.
The only class that inherits directly from UIElement is FrameworkElement, and all the elements you'll encounter in the Windows Presentation Foundation derive from FrameworkElement. In theory, UIElement provides the necessary structure of user interface events and screen rendering that can support various programming frameworks. The Windows Presentation Foundation is one such framework and consists of all the classes that derive from FrameworkElement. In a practical sense, you probably won't make much of a distinction between the properties, methods, and events defined by UIElement and those defined by FrameworkElement.
 
One popular class that inherits from FrameworkElement is Image. Here's the class hierarchy:
Object
--DispatcherObject (abstract)
------DependencyObject
----------Visual (abstract)
------------------UIElement
----------------------FrameworkElement
----------------------------Image
The Image class lets you easily include an image in a document or an application.