Friday, March 11, 2011

Canvas

The Canvas panel is the layout option closest to traditional graphical environments. You specify where elements go using coordinate positions. As with the rest of the Windows Presentation Foundation, these coordinates are device-independent units of 1/96 inch relative to the upper-left corner.

You may have noticed that elements themselves have no X or Y or Left or Top property. When using a Canvas panel, you specify the location of child elements with the static methods Canvas.SetLeft and Canvas.SetTop. Like the SetDock method defined by DockPaneland the SetRow, SetColumn, SetRowSpan, and SetColumnSpan methods defined by GridSetLeft and SetTop are associated with attached properties defined by the Canvas class. If you'd like, you can alternatively use Canvas.SetRight or Canvas.SetBottom, to specify the location of the right or bottom of the child element relative to the right or bottom of the Canvas.

Some of the Shapes classesspecifically, Line, Path, Polygon, and Polylinealready contain coordinate data. If you add these elements to the Children collection of a Canvas panel and don't set any coordinates, they will be positioned based on the coordinate data of the element. Any explicit coordinate position that you set with SetLeft or SetTop is added to the coordinate data of the element.

Many elements, such as controls, will properly size themselves on a Canvas. However, some elements will not (for example, the Rectangle and Ellipse classes), and for those you must assign explicit Width and Height values. It is also common to assign the Width and Height properties of the Canvas panel itself.

It's also possibleand often desirableto overlap elements on a Canvas panel. As you've seen, you can put multiple elements into the cells of a Grid, but the effect is often difficult to control. With Canvas, the layering of elements is easy to control and predict. The elements added to the Children collection earlier are covered by those added later.

//////

DockPanel (Code)

WrapPanel (CODE)

The panel most similar to StackPanel is WrapPanel. During the years that the Windows Presentation Foundation was being designed and created, the WrapPanel actually preceded the StackPanel. The WrapPanel displays rows or columns of elements and automatically wraps to the next row (or column) if there's not enough room. It sounds quite useful, but it turned out that developers were mostly using WrapPanel without the wrapping. These developers didn't know it at the time, but they really wanted a StackPanel.

WrapPanel is useful when you need to display an unknown number of items in a two-dimensional area. (Think of it as Windows Explorer in non-detail view.) It's likely that all these items will be the same size. WrapPanel doesn't require that, but it has ItemHeight and ItemWidth properties that you can use to enforce uniform height or width. The only other property that WrapPanel defines is Orientation, which you use the same way as for StackPanel.

It is difficult to imagine an application of WrapPanel that doesn't also involve ScrollViewer.  Lets see example with both:

//INSIDE CONSTRUCTOR OF WINDOWS
{
Title = "Explore Directories";

ScrollViewer scroll = new ScrollViewer();
Content = scroll;

WrapPanel wrap = new WrapPanel();
scroll.Content = wrap;

wrap.Children.Add(new FileSystemInfoButton());
}


I named FileSystemInfoButton for the FileSystemInfo object in System.IO. The two classes that derive from FileSystemInfo are FileInfo and DirectoryInfo. If you have a particular object of type FileSystemInfo, you can determine whether it refers to a file or to a directory by using the is operator.

The FileSystemInfoButton class derives from Button and stores a FileSystemInfo object as a field. The class has three constructors. The single-argument constructor is the one used most. It requires an argument of type FileSystemInfo, which it stores as a field. The constructor sets the button's Content to the Name property of this object. That's either the name of a directory or the name of a file. If this object is a DirectoryInfo, the text is bolded.

The parameterless constructor is used only when the program starts up and the window adds the first child to the WrapPanel or any other panel. The parameterless constructor passes a DirectoryInfo object for the My Documents directory to the single-argument constructor.


 


//////Contd////

GroupBox

Traditionally, a group of mutually exclusive radio buttons are children of a group box, which is a control with a simple outline border and a text heading. In the Windows Presentation Foundation, this is the GroupBox control, which is one of three classes that descend from HeaderedContentControl:

Control
---ContentControl
------HeaderedContentControl
---------Expander
---------GroupBox
---------TabItem

Because HeaderedContentControl derives from ContentControl, these controls have a Content property. The controls also have a Header property, which (like Content) is of type object. GroupBox adds nothing to HeaderedContentControl. Use the Header property to set the heading at the top of the GroupBox. Although this heading is customarily text, you can really make it whatever you want. Use Content for the interior of the GroupBox. You'll probably want to put a StackPanel in there.

//IN WINDOWS CONSTRUCTOR
{
Title = "Tune the Radio";
SizeToContent = SizeToContent.WindowandHeight;

GroupBox group = new GroupBox();
group.Header = "Window Style";
group.Margin = new Thickness(96);
group.Padding = new Thickness(5);
Content = group;
//
StackPanel stack = new StackPanel();
group.Content = stack;
//
stack.Children.Add( CreateRadioButton("No border or caption",
WindowStyle.None));
stack.Children.Add( CreateRadioButton("Single-border window",
WindowStyle.SingleBorderWindow));
stack.Children.Add(CreateRadioButton("3D-border window",
WindowStyle.ThreeDBorderWindow));
stack.Children.Add( CreateRadioButton("Tool window",
WindowStyle.ToolWindow));
//
AddHandler(RadioButton.CheckedEvent, new RoutedEventHandler(
RadioOnChecked));

}//End THE CONSTRUCTOR
RadioButton CreateRadioButton(string strText, WindowStyle winstyle)
{
RadioButton radio = new RadioButton();
radio.Content = strText;
radio.Tag = winstyle;
radio.Margin = new Thickness(5);
radio.IsChecked = (winstyle ==WindowStyle);

return radio;
}
//
void RadioOnChecked(object sender,RoutedEventArgs args)
{
RadioButton radio = args.Source as RadioButton;
WindowStyle = (WindowStyle)radio.Tag;
}


The checking and unchecking of sibling radio buttons happens automatically from either the mouse or keyboard. When you're using the keyboard, the cursor movement keys change the input focus among the sibling radio buttons. The space bar checks the currently focused button. All the program needs to do is monitor which button is being checked. (Some programs might also need to know when a button is losing its check mark.) It is usually most convenient to use the same event handler for sibling radio buttons. When writing code for the event handler, keep in mind that the IsChecked property has already been set.

It could be that you have a bunch of sibling radio buttons that comprise two or more mutually exclusive groups. To distinguish between these groups, use the GroupName property defined by RadioButton. Set GroupName to a unique string for each group of mutually exclusive buttons, and the multiple groups will be automatically checked and unchecked correctly. You can use the same GroupName property in your event handler to determine which group of buttons is affected.

Putting multiple elements into buttons

The following program creates a single button, but the button contains a StackPanel that has four children: an Image, a Label, and two Polyline objects. (Polyline inherits from Shape.)

Title = "Design a Button";

// Create a Button as content of the

Button btn = new Button();
btn.HorizontalAlignment =HorizontalAlignment.Center;
btn.VerticalAlignment =VerticalAlignment.Center;
btn.Click += ButtonOnClick;
Content = btn;

// Create a StackPanel as content of button
StackPanel stack = new StackPanel();
btn.Content = stack;

// Add a Polyline to the StackPanel.
stack.Children.Add(ZigZag(10));

// Add an Image to the StackPanel.
Uri uri = new Uri("pack://application:,,books.ICO"); // 32-pixels
BitmapImage bitmap = new BitmapImage(uri);
Image img = new Image();
img.Margin = new Thickness(0, 10, 0, 0);
img.Source = bitmap;
img.Stretch = Stretch.None;
stack.Children.Add(img);

// Add a Label to the StackPanel.
Label lbl = new Label();
lbl.Content = "_Read books!";
lbl.HorizontalContentAlignment =HorizontalAlignment.Center;
stack.Children.Add(lbl);

// Add another Polyline to the stackpanel
stack.Children.Add(ZigZag(0));

}

Polyline ZigZag(int offset)
{
Polyline poly = new Polyline();
poly.Stroke = SystemColors.ControlTextBrush;
poly.Points = new PointCollection();

for (int x = 0; x <= 100; x += 10)
poly.Points.Add(new Point(x, (x +offset)% 20));
return poly;
}

void ButtonOnClick(object sender,RoutedEventArgs args)
{
MessageBox.Show("The button has been clicked", Title);
}

Viewbox

Scrollbars represent the traditional solution for fitting more elements than space allows. The Windows Presentation Foundation offers another solution called the Viewbox.

ScrollViewer

The ScrollViewer has two properties that govern the visibility of the vertical and horizontal scroll bars. By default, the VerticalScrollBarVisibility property is the enumeration member ScrollBarVisibility.Visible, which means that the scroll bar is always visible, but it's inactive when it's not needed.

The default setting of the HorizontalScrollBarVisibility property is ScrollBarVisibility.Disabled, which means that the scroll bar is never visible.

Another option is ScrollBarVisibility.Auto, which means that the scroll bar appears only when it's needed. You might try setting the VerticalScrollBar property to this member and also decrease the number of buttons to something that can fit on your screen. As you make the window tall enough for the vertical scroll bar to disappear, you'll notice that all the buttons get wider because they have additional space in which to stretch! (Of course, you can avoid that effect by setting the HorizontalAlignment property of the buttons to HorizontalAlignment.Center.)

You can set the HorizontalScrollBarVisibility property to ScrollBarVisibility.Visible or ScrollBarVisibility.Auto. Now when you make the window too narrow for the buttons, a horizontal scroll bar lets you scroll the right sides into view. Without a horizontal scroll bar, when you make the window narrow, the ScrollViewer gives the StackPanel a narrower width. A very narrow StackPanel makes the buttons less wide, and button content is truncated. With a horizontal scroll bar, the StackPanel gets the width it needs.