Telerik RadControls For Winforms Courseware
Telerik RadControls For Winforms Courseware
Managing Editor
Noel Rice
Authors
Noel Rice Rachel Hagerman
Cover Design
Matt Kurvin
663-665 665-669 669-672 672-731 731 732 732 732-734 734-735 735-745 745 746 746 746 746-749 749-750 750-751 751-752 752-755 755
This is the fifth courseware Falafel has written for Telerik, the first two being on RadControls for ASP.NET and Telerik Reporting. This hands-on training material will be of great help to individuals, teams, and the community as a whole, and will assist them in quickly learning the power of RadControls and experience their true value. It has been a fantastic experience to work with Falafel Software on producing the Telerik RadControls for WinForms courseware, and they have once again proved that they are skilled professionals, who are ready to go to great extends for their customers. On behalf of the whole Telerik team, I would like to personally thank Noel Rice for his kindliness, understanding, and most of all attention to detail without him we would not have been able to produce this thorough and extensive courseware on RadControls for WinForms. I hope you enjoy this reading and that it increases your proficiency in RadControls, bringing your valuable projects to a great success. Nikolay Diyanov Unit Manager, RadControls for WinForms Telerik Inc.
Introduction
You have used standard Microsoft WinForms controls and want to learn the Telerik RadControls for WinForms approach to application building. You have used RadControls for WinForms and want to make your knowledge more comprehensive.
2.2 What Do You Need To Have Before You Read This Courseware?
Computer Setup
Windows XP Professional or Windows Vista Service Pack 2. Microsoft .NET Framework 3.5. Microsoft Visual Studio 2008 RadControls for WinForms. You can purchase RadControls for WinForms from: http://www.telerik.com/purchase.aspx
or download the trial from: http://www.telerik.com/products/winforms.aspx Learn more about system requirements for RadControls for WinForms here (http://www.telerik.com/products/winforms/resources/system-requirements.aspx).
A list of the objectives to be accomplished in the chapter. Abrief introduction to orientate you to the "why and where" each control should be used. A"Getting Started" tutorial to get your feet wet with the control. A tour of the design-time interface and a brief overview of significant control properties or groups of properties. A guide to programmatic management of the control. A brief review of the objectives that were accomplished.
Chapter Summary
Buttons
Editors
This chapter shows how to retrieve information from the user with the RadSpinEditor, RadDateTimePicker, RadMaskedEditBox, RadTextBox and RadColorDialog controls. The chapter begins with a brief exploration of basic usability for each control and highlights special features. The chapter includes explanation how to implement tool tips, validate user entry and control specific information on edit masks, date formats and internationalization support.
Menus
You will learn how to add drop-down and context menus to your application using RadMenu, RadContextMenu and RadContextMenuManager controls. We begin with a tour of usability and feature highlights, then learn how to build menus at design-time using the Menu Designer. You will learn common menu item collection programmatic tasks such as adding and removing menu items,locating and modifying menu items. The unique aspects of RadContextMenu are discussed including programmatically popping up the context menu in a specific screen location.Finally, the chapter introduces the RadRibbonBar andRadApplicationMenu controls.
Page View
This chapter explores tabbed interfaces and managing controls within associated content panels. You will perform common Items collection programmatic tasks such as adding and removing tabs, iterating, locating and selecting tabs. The chapter also explains how to implementhandle layout and dimensions, overflow, tab images and text.
List Controls
Thischapter explores creating tabbedand paneled interfaces and managing controls within associated content panels. The chapter starts with a tour of usability and feature highlights then demonstrates how to perform common Items collection programmatic tasks such as adding and removing tabs, iterating, locating and selecting tabs. The chapter also explains how to implement tab drag and drop, handle layout and dimensions, overflow, tab images and text.
Data Binding
In this chapter you will learn which controls have DataSource properties and the bindable types that can be assigned to them. The chapter starts with examples of binding to simple arrays and lists of objects, then moves on to use BindingSource to bind to database, business objects and web services. The chapter also shows how to bind simple controls using the DataBindings property and how to bind LINQ data sources.
User Feedback
Learn how to provide user feedback using RadStatusStrip, RadTrackBar, RadWaitingBar, RadProgressBar and RadLabel controls. You will also learn the appropriate circumstances to use a RadWaitingBar vs a RadProgressBar, how to use the RadStatusStrip at design time and programmatically and how to host hosted a
Command Bar
This chapter shows how to create tool strips that can be built up from multiple RadControls, dragged and docked within your user interface, resized, re-arranged, and customized by the user. The chapter explains the basic structure of the tool strip and how to include elements within the strip items.
Forms
This chapter shows how the special RadForm, ShapedForm and RadRibbonForm classes can be inherited from to create themeable, custom shaped forms to complete and polish the look-and-feel of an application. You will use the new project item templates to create instances of each form class. The chapter demonstrates how RadTitleBar is used as a replacement for the built-in Windows form title bar. Finally, the chapter introduces the RadMessage box as a themable replacement for the standard MessageBox.
Calendar
This chapter focuses on the RadCalendar and includes how to use the extensive customization features to completely tailor the calendar header, calendar footer, number of displayed months, the number of rows and columns, date ranges, selected and focused dates, the first day of the week as well as the title and navigation areas of the calendar. The chapter also explains how to work with the special days collection to mark specific days or repeating events.
Shortcuts
This chapter explains how input bindings are created and initiated by RadControl actions. The chapter demonstrates creating and assigning bindings programmatically.
Scheduler
In this chapter you will learn how to work with RadScheduler, to work with appointments, reminders and views. Additionally, you will learn how to customize the appearance of the control components.
Chart
In this chapter you will build a simple chart with static items and also bind data to the chart. The chapter tours the basic RadChart elements as well as the types of charts that are available. You will learn how to use the tools in the designer to help navigate the many RadChart capabilities.You will create and configure many of the chart elements programmatically, including the chart series, items, legend and chart title.
Grid
This chapter explores the RadGridView control including design time supportusing the Smart Tag, Property Builder and Properties window to configure the grid and to bind the grid to data. You will learn how to add special purpose column types at design-time and in code, how to group/filter/sort data based on user input at runtime, by hand at design-time and programmatically in code. You will display hierarchical data from multiple related tables in the grid. You will use the RadGridView Virtual Mode feature to take low-level control over the grid's refresh process. You will learn how to bind RadGridView to LINQ data sources for lightening fast performance. Finally you will use multiple methods of exporting grid data to Excel and out through the Telerik Reporting engine.
Multi-Column ComboBox
Tree
This chapter shows how to display, navigate and manage hierarchical data using the RadTreeView control. RadBreadCrumb is introduced to help the user keep track of their location in deeply nested hierarchical structures. The chapter includes topics on tree view support for implementing drag-and-drop and context menus. RadTreeView specific data binding issues include binding to self referencing data, binding to related data, writing to and from XML and load-on-demand. The chapter covers techniques for adding and removing nodes programmatically, iterating and locating nodes, editing nodes and reordering nodes.
Wizard
This chapter reveils how with a few click you can create your very own step-by-step wizard to make your installations with less efforts and with better appearance and functionality.
RadControls for Winforms edit controls are highly customizable, themable, intelligent components for controlled data input in Windows Forms applications that include text boxes, masked edit boxes, date time pickers, spin editor and a color dialog.
RadPageViewsupply intuitive navigation between application areas. RadPageViewsupplies the basis for building tabbed interfaces with rich formatting and behavior.
RadListControl and RadDropDownList controls are based on the Telerik Presentation Foundation and have a great deal of flexibility in what content can be included in theirs lists and how the content is arranged. Each item in the list can have specially formatted. The layout and formatting is highly configurable.
RadControls that have a DataSource property can databind to any object that implements IList or IListSource including array and generic lists, business objects, DataTable and DataSets, LINQ data sources, web services and WCF data. The binding mechanism is consistent between controls allowing you to best leverage your knowledge.
Telerik RadControls provide compelling user feedback so that your user knows what just happened, what's going on now and what's coming next. Enhanced themeable trackbars, status strips, progress bars, waiting bars and labels keep your user engaged.
RadShortcutprovide a simple, comprehensive way to add keyboard shortcuts for all RadControls on a Windows Form.
RadCommandBarfully themeable tool strip that provides unprecedented flexibility.More than just a collection of buttons, RadCommandBar hosts any RadControl, including dropdown lists, text boxes, split buttons, drop-down buttons, toggle buttons and more. Strips can be moved, rearranged and resized at run time for easy end-user customization.
RadForm and ShapedForm let you design styled Windows forms of just about any shape and style for sharp, consistent user interfaces.
For interactive, unique navigation and form "real estate" management, RadDock, RadRotator and RadCarousel let you catch your users attention and make wise use of form space at the same time.
RadCalendar is a lightweight yet highly advanced date input control for Windows Forms. Zoom, select multiple dates, view several months at once, style special dates, use it as a date picker, or even add a Hebrew calendar to your forms.
RadScheduler is a highly-customizable appointment presentation component that offers rich Outlook-style functionality. The product delivers swift performance, simplified deployment and limitless customization capabilities and is suitable for use in large-scale enterprise applications.
RadChart is a powerful business data presentation tool that can show your data off with striking impact. RadChart comes with many customizable chart types and skins to tailor the behavior and look of each chart.
RadGridView is a powerful, highly performant grid component developed on top of the innovative Telerik Presentation Foundation, which allows for unprecedented performance, extensibility, customizability, and ease of use.
RadMultiColumnComboBox is a special case of combobox control with a RadGridView integrated in its dropdown. The drop down display has the rich capabilities of the grid view, but you can stilluse the control in a limited amount of space.
10
RadTreeView is a supercharged tree view component for Windows Forms that displays, manages, and navigates hierarchical data structures. The product offers advanced features like drag-and-drop, load-on-demand, context menus and data binding.
The RadWizard control helps you break a complex process into separate steps and provide your users with the opportunity to guide the process, just like the well-known installation wizards. RadWizard supports both Wizard97 and Wizard Aero specifications and provides developers with predesigned Welcome, Completion and Internal pages.
The most innovative user interfaces can be created in a flash with Telerik Windows Forms RibbonBar. In is an easy-to-use implementation of the Microsoft Office 2007 "ribbon' UI, which will allow you to codelessly organize all the functionality of you application into a single compact toolbar control. What is more, it can be coupled with RadRibbonForm or extended ease of use and easy imeplementation. And now, it also support BackstageView.
11
The projects in this learning guide will assume the following: 1. Thatyou will add the following assembly references and to the "Imports" (VB) or "uses" (C#) statements of your projects to reference the Telerik.WinControls and Telerik.WinControls.UI namespaces: [VB] Including the Telerik.Web.UI Namespace Imports Telerik.WinControls Imports Telerik.WinControls.UI [C#] Including the Telerik.Web.UI Namespace using Telerik.WinControls.UI; using Telerik.WinControls; 2. You may need to change the path to assembly references within the supplied projects to local paths for your Telerik assemblies.
12
Buttons
3.1 Objectives
Learn usage and basic characteristics for each type of RadControls buttons. Learn how to add members to the Items collection for drop down and split buttons. Respond to events for the buttons and Items collection members. Explore the design time interfaces to configure the buttons. Learn how to manipulate ToggleState and handle ToggleState related events.
3.2 Introduction
These themable buttons replace their standard WinForms counterparts and add robust data binding, state management and design options.Developed to be very similar to the existing Windows Forms controls, they also allow you to take advantage of the features of RadControls, such as themes, rotation and transparency, images and text. Along with the button, radio button and checkbox, you get:
"Repeat" buttons that continuously fire as long as the button is held down A "Toggle" button that changes state like a checkbox. The state can be on, off and indeterminate. A "Drop Down" button displays a list of selections that can be clicked. A "Split" button is like the drop down but has a button and a drop down portion. If you click the arrow, the list drops down.One item in the list is considered the "default" andclicking the button acts as if that default item is being clicked. The repeat and toggle buttons were inspired by analagous buttons found in the Windows Presentation Foundation (WPF).
13
14
5. In the Properties window, set the form'sSize property to "700, 500" and the Text property to "Buttons". 6. From the Toolbox, add a RadPanel to the form. Set the panel Dock property to "Top" and Text to "". Drag the bottom edge of the panel down so that it takes up about a third of the form space. The panel layoutshould now look something like this:
15
7. Add several themes from the Toolbox: OpenFileDialog (from the standard MS controls), AquaTheme, Office2007SilverTheme, MiscellaneousTheme and DesertTheme. The component tray should now have the components shown in the screenshot below:
8. From the Dialogs tab of the Toolbox add a OpenFileDialog component. Set the Filter property to "jpg (*.jpg)|*.jpg|png (*.png)|*.png". 9. Set the RadForm ThemeName property to ControlDefault 10. Set the RadPanel ThemeName property to ControlDefault. 11. Add the following buttons to the top of the RadPanel (from left to right) and set properties:
RadButton: Name = "btnLoad", Text = "Load", ThemeName = "ControlDefault", BackColor = "Transparent". RadToggleButton: Name ="tbBackgroundColor", Text = "Contrast Background", ThemeName = "ControlDefault", BackColor = "Transparent". RadLabel: Text = "Images:", ThemeName = "ControlDefault", BackColor = "Transparent". RadDropDownButton: Name = "ddbImages",Text = "Choose Images", ThemeName = "ControlDefault", BackColor = "Transparent", DropDownDirection = Right. RadLabel: Text = "Size Mode:", ThemeName = "ControlDefault", BackColor = "Transparent". RadSplitButton: Name = "spSizeMode", Text = "Choose a Size Mode", ThemeName = "ControlDefault",
16
12. Below the row of buttons, add two standard GroupBox controls:
BackColor = "Transparent", Text = "Border Style". BackColor = "Transparent", Text = "Image Rotation".
Name = "rbNone", Text = "None", ThemeName = "ControlDefault", Tag = "0". Name = "rbFixedSingle", Text = "Fixed Single", ThemeName = "ControlDefault", Tag = "1". Name = "rbFixed3D", Text = "Fixed 3D", ThemeName = "ControlDefault", Tag = "2", IsChecked = "True". Using the Event ( ) tab of the Properties Window add an event handler "BorderStyleClick". Note: We will add the code to this event handler later. Notice that the Tag properties aboveare set to 0, 1, 2. These correspond to the raw integer values of the BorderStyle enumeration. Later, when a button is clicked on, we will retrieve the tag value and cast it to be a BorderStyle.
14. In the "Image Rotation" group box add the following buttons:
RadRepeatButton: Name = "rbRotate", Text = "Rotate", Interval = "1000", ThemeName = "ControlDefault". RadCheckBox: Name = "cbFlip", Text = "Flip", ThemeName = "ControlDefault". RadCheckBox: Name = "cbHorizontalFlip", Text = "Horizontal Flip", ThemeName = "ControlDefault". RadCheckBox: Name = "cbVerticalFlip", Text = "Vertical Flip", ThemeName = "ControlDefault". Now the panel should look something like the screenshot below:
17
15. Below the RadPanel add a standard PictureBox control. Size it to take up most of the remaining space on the form. Set the Anchor property to "Top, Bottom, Left, Right".
18
2. Select the new RadMenuItem with the mouse and set the following properties in the Properties Window: Name = "btnSizeModeNormal", Text = "Normal" and Tag = "0". In theEvents tab ( ) of the Properties Window, locate the Click event and add "SizeModeClick" as the event name and hit Enter to create the event handler. 3. Add four more RadMenuItems with the following Properties:
Name = "btnSizeModeStretch", Text = "Stretch Image", Tag = "1". Set the Click event to "SizeModeClick". Name = "btnSizeModeAutoSize", Text = "AutoSize", Tag = "2". Set the Click event to "SizeModeClick". Name = "btnSizeModeCenterImage", Text = "Center Image", Tag = "3". Set the Click event to "SizeModeClick". Name = "btnSizeModeZoom", Text = "Zoom", Tag = "4". Set the Click event to "SizeModeClick".
Add Code
Here we will add some minimal functionality to the RadButton to load an image, the RadSplitButton to change the size mode and the RadRadioButtons to change the PictureBox BorderStyle. 1. Add references to the "Imports" (VB) or "uses" (C#) section of code: [VB] Adding References Imports Telerik.WinControls Imports Telerik.WinControls.UI [C#] Adding References using Telerik.WinControls.UI; using Telerik.WinControls; 2. In the design view, double-click the "Load" button to create a Click event handler. Add the code below to the handler. This codeuses the OpenFileDialog to get the name of a "jpg" or "png" image file. A new Bitmap object is created and assigned to the PictureBox Image. [VB] Handling the Load Button Click Event Private Sub btnLoad_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnLoad.Click If openFileDialog1.ShowDialog() = System.Windows.Forms.DialogResult.OK Then Dim bitmap As Bitmap = New Bitmap(openFileDialog1.FileName)
19
[VB] Handle the Load Event Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load sbSizeMode.DefaultItem = sbSizeMode.Items("btnSizeModeZoom") sbSizeMode.Text = sbSizeMode.Items("btnSizeModeZoom").Text sbSizeMode.DefaultItem.PerformClick() End Sub [C#] Handle the Load Event private void RadForm1_Load(object sender, EventArgs e) { sbSizeMode.DefaultItem = sbSizeMode.Items["btnSizeModeZoom"]; sbSizeMode.Text = sbSizeMode.Items["btnSizeModeZoom"].Text; sbSizeMode.DefaultItem.PerformClick(); } 4. Add the code below to handle the RadMenuMenuButton Click event. Get the RadMenuItem from the "sender" parameter passed in. The Tag property will contain the enumeration value associated with the menu item. Cast the Tag value first from object to Int32, then to PictureBoxSizeMode and assign it to the SizeMode property of the PictureBox. Finally, set the split button Text property to the menu item's Text. [VB] Handle the RadMenuButtonItem Click Private Sub SizeModeClick(ByVal sender As Object, ByVal e As EventArgs) Dim item As RadMenuButtonItem = TryCast(sender, RadMenuButtonItem) pictureBox1.SizeMode = CType(Convert.ToInt32(item.Tag), PictureBoxSizeMode) sbSizeMode.Text = item.Text End Sub [C#] Handle the RadMenuButtonItem Click private void SizeModeClick(object sender, EventArgs e) { RadMenuButtonItem item = sender as RadMenuButtonItem; pictureBox1.SizeMode = (PictureBoxSizeMode)Convert.ToInt32(item.Tag);
20
7. In the form's Load event, add the following lines of code to apply the "Desert" theme to the entire application. Note: you will need to add Telerik.WinControls to the "Imports" (VB) or "using" (C#) section of code. [VB] Setting the Application Theme
21
If you want to allow the user to tab through buttons and have eachbutton visibly receive focus, set each button's AllowShowFocusCues property to true. The second button in the image below has the focus and AllowShowFocusCues is true.
22
Tasks
From the Smart Tag Tasks menu you can Open Theme Builder to style all aspects of your control, select New Theme Manager to add a Theme Manager component to the component tray, Edit UI elements to browse all of the elements of the button and to change properties for any element. The Theme Name drop down lets you pick an existing theme to style your control.
Learning center
The Learning center lets you navigate to a web browser with online help for the currently selected button control or to the online support forums.
Search
Enter search criteria in the edit space provided and click the Search link to navigate directly to search on the Telerik web site.
Collection Editor
The RadItem Collection Editor is initiated by the RadDropDownButton and RadSplitButton Items property ellipses or from the Smart Tag "Edit Items" entry. The editor lets you add, edit properties and delete items that populate the drop down list of your button.
23
The Add button contains menu item types RadMenuItem, RadMenuButtonItem, RadMenuComboItem, RadMenuHeaderItem and RadMenuSeparatorItem.
24
[VB] Adding Multiple Item Types radDropDownButton1.Items.Add(New RadMenuItem("Menu Item")) radDropDownButton1.Items.Add(New RadMenuButtonItem("Button Item")) radDropDownButton1.Items.Add(New RadMenuSeparatorItem()) radDropDownButton1.Items.Add(New RadMenuHeaderItem("Header")) Dim comboItem As New RadMenuComboItem() comboItem.DropDownHeaderText = "Click One!" comboItem.Items.Add(New RadMenuItem("One")) comboItem.Items.Add(New RadMenuItem("Two")) comboItem.Items.Add(New RadMenuItem("Three")) radDropDownButton1.Items.Add(comboItem) [C#] Adding Multiple Item Types radDropDownButton1.Items.Add(new RadMenuItem("Menu Item")); radDropDownButton1.Items.Add(new RadMenuButtonItem("Button Item")); radDropDownButton1.Items.Add(new RadMenuSeparatorItem());
25
3. Make sure you have the following references in your "Imports" (VB) or "uses" (C#) section of your code: [VB] Adding Namespace References Imports System ' Supports IDictionaryEnumerator Imports System.Collections Imports System.Drawing
26
27
28
29
ToggleState: This property may be Off, On or Indeterminate. Checked: This is a simple boolean that is true when the button is checked (ToggleState = On). It's provided for compatibility only. IsThreeState: When this property is enabled, the user can cycle through the three states by clicking the button. If IsThreeState is off, you can still set the state of the button programmatically. ToggleStateChanging: This event occurs before the ToggleState property of the button is about to be changed. Using the StateChangingEventArgs passed in to the event, you can look at the OldValue (the
30
ToggleStateChanged: The StateChangedEventArgs passed to this event only contain a ToggleState property. The event is not cancelable.
ToggleState Walkthrough
In the "Getting Started" project we handled the "Border Style" radio buttons with a simple Click event and retrieved the Tag value. In this example we're going to exercise the button's ToggleState, both setting and retrieving the ToggleState On, Off and Indeterminate values in relatively complex relationships. In this case we're going to leave the IsThreeState property off and work with the ToggleState programmatically. The "Contrast Background" will handle the ToggleStateChanged event to see if the ToggleState is On or Off, i.e. functionally equivalent to using IsChecked. If ToggleState is off, a color selected from a pixel in the center of the picture will be used as the background color. If ToggleState is on, a contrasting color will be calculated and used as the background color. The checkboxes in the "Image Rotation" group box of controls will take all three toggle states into account. When the "Flip" check box toggle state changes, both the "Flip Horizontal" and "Flip Vertical" check boxes are set to the matching toggle state. When either the horizontal or vertical check boxes are toggled, the logic is:
If both are On, the "Flip" check box is set On. If both are Off, the "Flip" check box is set Off. If only the horizontal or vertical check box is on, then the "Flip" check box toggle state is set to Indeterminate.
Based on the setting of these three checkboxes, a RadRepeater button will rotate and flip the image.
31
32
Clicking the "Contrast Background" color switches the background color to a contrasting color:
33
34
35
36
3.6 Summary
In this chapter you took a tour of the various types of buttons available in the RadControls for Winforms suite. You learned the basic characteristics, behaviorand important properties of each button type. You used several design time interfaces to configure the buttons. You worked with the Items collections of both RadDropDownButton and RadSplitButton. You responded to events both from the buttons and from individual Items collection members. Finally, you learned how to manipulate button ToggleState and how to handle ToggleState related events.
37
Editors
4.1 Objectives
Learn usage and basic characteristics for each type of editor. Learn how to retrieve user information from RadTextBox, RadMaskedEditBox, RadSpinEditor, RadDateTimePicker, and RadColorDialog controls. Learn how to use edit masks and formats. Learn how to set tool tips. Learn how to validate input and different strategies for responding to incorrect data.
4.2 Introduction
RadControls for Winforms edit controls are highly customizable, themable,intelligent components for controlled data input in Windows Forms applications. They include...
RadTextBox: A themeable alternative to the standard TextBox control with enhanced properties such as NullText to hold prompt messages when there is no entry. RadMaskedEditBox: Addsinput validation and masks, such as date, IP Address, SSN, phone number, digits, and decimals. This control is also themable and has a NullText property. RadDateTimePicker: Allows the user to enter dates directly or using a drop-down calendar. You can control the date format, set minimum and maximum dates, set the calendar to display for a specific culture and display a prompt when the control has a "null date". RadSpinEditor: A numeric entry control that allows direct input, keyboard control or the user may click on the up-down arrows. You can control the minimum and maximum value and the increment amount. You can also tailor formatting details such as the thousands separator and decimal places. RadColorDialog: A color dialog replacement with lots of bells and whistles including four different view tabs, Basic, Professional, Web and System, hex value entry, eye dropper control and custom colors.
38
39
Size = 630, 350 MinimumSize = 630, 350 Text = "Checkout" ThemeName = "Office2007Silver"
3. Drop three standard GroupBox controls and a RadButton on the form. Arrange them to have roughly the same proportions as the example below:
40
The top group box: Name = "gbShipTo", Anchor = Top, Left, Right, BackColor = Transparent,TabIndex = 0, Text = "Ship to". The bottom left group box: Name = "gbDelivery", Anchor = Top, Bottom, Left, BackColor = Transparent,TabIndex = 1, Text = "Deliver By". The bottom right group box: Name = "gbGiftOptions", Anchor = Top, Bottom, Left, Right, BackColor = Transparent,TabIndex = 2, Text = "Gift Options". The RadButton: Name = "btnPlaceOrder", Anchor = Bottom, Right, TabIndex = 3, Text = "Place Order", Tag = "Place Order".
5. Add the following controls to the "gbShipTo" group box: 1. RadLabel: Text = "Name:". 2. RadTextBox: Name = tbName, Anchor = Left, Right", NullText = "<Enter Name>", Tag = "Name", TabIndex = 0. 3. RadLabel: Text = "Address:". 4. RadTextBox: Name = tbAddress, Anchor = Left, Right", NullText = "<Enter Address>", Tag = "Address", TabIndex = 1. 5. RadLabel: Text = "City:". 6. RadTextBox: Name = tbCity, NullText = "<Enter City>", Tag = "City", TabIndex = 2. 7. RadLabel: Text = "State:". 8. RadMaskedEditBox: Name = meState, MaskType = Standard, Mask = "LL", Tag = "State", TabIndex = 3. 9. RadLabel: Text = "Zip:". 10. RadMaskedEditBox: Name = meZip, MaskType = Standard, Mask = "99999-9999", Tag = "Zip", TabIndex = 4.
41
6. Add the following controls to the "gbDelivery" group box: 1. RadLabel: Text = "Business Days". 2. RadTextBox: Name = seDeliver, CausesValidation = False, Tag = "Business Days", TabIndex = 0. 3. RadLabel: Text = "or...". 4. RadLabel: Text = "Deliver by:". 5. RadDateTimePicker: Name = "dtDeliver", Tag = "Deliver by", TabIndex = 1
7. Add the following controls to the "gbGiftOptions" group box: 1. RadCheckBox: Name = "cbGiftWrap", BackColor = Transparent, Text = "Gift Wrap?", Tag = "Gift Wrap". 2. RadButton: Name = "btnChooseColor", Anchor = Top, Left, Right, Enabled = False, Text = "Choose Wrap Color", Tag = "Choose Wrap Color". 3. RadLabel: Text = "Note:". 4. RadTextBox: Name = "tbNote", Anchor = "Top, Bottom, Left, Right", Enabled = False, Tag = "Gift Wrap Note".
8. Double-click the "Gift Wrap?" check box to create a ToggleStateChanged event handler. First add Telerik.Wincontrols.Enumerations to your "Imports" (VB) or "uses" (C#) section of code. Then add the following code to the ToggleStateChanged event handler: [VB] Handling the ToggleStateChanged Event Private Sub cbGiftWrap_ToggleStateChanged(sender As Object, args As
42
10. Double click the "Place Order" button to create a Click event handler. Add the code below to the event handler. After ValidateControls() verifies the information on the form, the data is collected from the form and displayed using a RadMessageBox. Note: RadMessageBox is a themeable, flexiblereplacement for the standard MessageBox class. Also note that no validation or data collection is actually performed in this version of the project. [VB] Creating a Click Event Handler Private Sub btnPlaceOrder_Click(sender As Object, e As EventArgs) If ValidateControls(Me.Controls) Then Dim caption As String = "Order Summary" Dim message As String = "Thank you for your order" + Environment.NewLine + GetFormData
43
If you want to theme all controls to match the RadForm, you can create a method similar to this example that recursively sets the ThemeName for all RadControl types on the form. Here is the same form with the "Desert" theme set:
44
[VB] Setting the ThemeName for all Controls ' cycle through the controls collection recursively and set the ' theme for all rad controls Private Sub SetTheme(controls As Control.ControlCollection) For Each control As Control In controls If TypeOf control Is RadControl Then (TryCast(control, RadControl)).ThemeName = Me.ThemeName End If If control.Controls.Count > 0 Then SetTheme(control.Controls) End If Next End Sub '... ' call it from the form's constructor: Utils.SetTheme(Me.Controls) [C#] Setting the ThemeName for all Controls // cycle through the controls collection recursively and set the // theme for all rad controls private void SetTheme(Control.ControlCollection controls) { foreach (Control control in controls) { if (control is RadControl) (control as RadControl).ThemeName = this.ThemeName; if (control.Controls.Count > 0) SetTheme(control.Controls); } } //... // call it from the form's constructor: Utils.SetTheme(this.Controls); To set the theme for a RadMessageBox, call the static RadMessageBox.SetThemeName() method prior to calling Show().
45
Tasks
From the Smart Tag Tasks menu you can Open Theme Builder to style all aspects of your control, select New Theme Manager to add a Theme Manager component to the component tray, Edit UI elements to browse all of the elements of the editor and to change properties for any element. The Theme Name drop down lets you pick an existing theme to style your control.
Learning center
The Learning center lets you navigate to a web browser with online help for the currently selected control or to the online support forums.
Search
Enter search criteria in the edit space provided and click the Search link to navigate directly to search on the Telerik web site.
Multi-Line Behavior
When the MultiLine property is true, text can span more than one line and the text box can be resized.In
46
You can programmatically set multiple lines of text by assigning an array of strings to the Lines property or a single string with embedded new line characters to the Text property. To indicate new lines you can add the System.Environment.NewLine string or use the language specific carriage return/line feed ("& vbCr & vbLf" in Visual Basic .NET and the "\r\n" escape characters in C#). [VB] Assigning multiple lines of text Private Sub Form1_Load(sender As Object, e As EventArgs) radTextBox1.Lines = New String(3) {"It was the best of times,", "it was the worst of times,", "it was the age of wisdom..."} radTextBox1.Text = "It was the best of times," + Environment.NewLine + "it was the worst of times," + Environment.NewLine + "it was the age of wisdom..." radTextBox1.Text = "It was the best of times," & vbCr & vbLf & "it was the worst of times," & vbCr & vbLf & "it was the age of wisdom..." End Sub [C#] Assigning multiple lines of text private void Form1_Load(object sender, EventArgs e) { radTextBox1.Lines = new string[3] { "It was the best of times,", "it was the worst of times,", "it was the age of wisdom..."}; radTextBox1.Text = "It was the best of times," + Environment.NewLine +
47
Auto Completion
The "Auto Completion" feature provides "type ahead" and selection from a list of choices. You may have noticed this behavior in some web browsers as you type in a URL. To turn on this ability, set the AutoCompleteMode property from "None" to "Suggest", "Append" or "SuggestAppend". "Suggest" drops down a list of selections for the user to choose from and "Append" automatically completes the entry to the nearest match in the list. You can see the effect of how "SuggestAppend" combines both behaviors in the screenshot example below, where the entry starting with "c:\p" is automatically appended with "rogram Files" and a list of suggestions also appears.
Use the AutoCompleteSource property to designate where the suggestions come from, i.e. "FileSystem", "CustomSource", etc. To define your own auto completion suggestions, add to the AutoCompleteCustomSource array of strings and set the AutoCompleteMode to "CustomSource". The example below creates a custom list of choices:
[VB] Customizing Auto Complete Behavior tbAutoComplete.AutoCompleteSource = AutoCompleteSource.CustomSource Dim containers As New AutoCompleteStringCollection() containers.Add("Box") containers.Add("Bundle") containers.Add("Pallet") containers.Add("Carton") tbAutoComplete.AutoCompleteCustomSource = containers tbAutoComplete.AutoCompleteMode = AutoCompleteMode.SuggestAppend [C#] Customizing Auto Complete Behavior tbAutoComplete.AutoCompleteSource = AutoCompleteSource.CustomSource;
48
Null Text
This unique enhancement displays a prompt when there is no entry. The prompt appears as lightly colored text (SystemColors.GrayText) and disappears when the user tabs into the text box.
[VB] Setting Null Text tbContainer.Text = [String].Empty tbContainer.NullText = "Enter a container name" [C#] Setting Null Text tbContainer.Text = String.Empty; tbContainer.NullText = "Enter a container name";
Events
To be notified when the contents of the text box changes, hook up the TextChanging and TextChanged events. Arguments supplied to TextChanging provide the NewValue and OldValuestring properties; set Cancel true to prevent the text from changing. [VB] Handling the TextChanging Event Private Sub tbContainer_TextChanging(sender As Object, e As Telerik.WinControls.TextChangingEventArgs) btnPlaceOrder.Enabled = e.NewValue.Length > 0 End Sub [C#] Handling the TextChanging Event private void tbContainer_TextChanging(object sender, Telerik.WinControls.TextChangingEventArgs e) { btnPlaceOrder.Enabled = e.NewValue.Length > 0; } The TextChangedEvent fires as each character is typed. Use the Text or Lines property of the text box to access text box contents:
[VB] Handling the TextChanged Event Private Sub tbContainer_TextChanged(sender As Object, e As EventArgs) btnUseContainer.Text = "Use " + (TryCast(sender, RadTextBox)).Text + " container" End Sub [C#] Handling the TextChanged Event
49
Height
By default, both RadTextBox and RadMaskedEdit box cannot be resized vertically;set the MultiLine property true to size either control freely.
Borders
To remove the border of a text box so that it looks more like a label, you need to locate the TextBoxElement and set its visibility to "Collapsed". The background for this will be presented in the chapter "Telerik Presentation Foundation", but for now, either use the code below... [VB] Hiding Text Box Borders (TryCast(tbMultiLine.TextBoxElement.Children(2), BorderPrimitive)).Visibility = ElementVisibility.Collapsed [C#] Hiding Text Box Borders (tbMultiLine.TextBoxElement.Children[2] as BorderPrimitive).Visibility = ElementVisibility.Collapsed; ...or, click the Smart Tag "Edit UI Elements" link, locate the "BorderPrimitive" element in the tree view, navigate to the Appearance properties and set the Visibility property to "Collapsed".
50
You can find the complete source for this project at: \Editors\<VB|CS>\EditorsOverview
Masks
The mask helps the user know what is expected and does not allow incorrect input. Instead ofthe Text property use the Value property. Value is an Object where the actual type varies depending on the type of mask you are using. The critical properties are MaskType and Mask. MaskType can be None, Standard,
51
Standard Masks
The table below describe the mask characters that can be used when theMaskTypeproperty is set toStandard. Mask Character 0 9 Description Digit, required. This element will accept any single digit between 0 and 9. Digit or space, optional. Digit or space, optional. If this position is blank in the mask, it will be rendered as the character in thePromptChar (http://www.telerik.com/help/winforms/editorsmaskededitbox-working-with-radmaskededitbox.html)property. For example, "$######.##" displays as a literal "$", accepts a numeric amount with six places and two places to the right of the decimal, i.e.$123456.56. Accepts letters only. Escapes a mask character, turning it into a literal. "\\" is the escape sequence for a back slash. For example, "\# ###", i.e. "# 123". Letter, optional. Character, required. Character, optional. Alphanumeric, required. Accepts any symbol. Alphanumeric, optional. Decimal placeholder. Thousands placeholder. Time separator. Date separator. Currency symbol. Shift down. Converts all characters that follow to lowercase. Shift up. Converts all characters that follow to uppercase. Disable a previous shift up or shift down. Escape. Escapes a mask character, turning it into a literal. "\\" is the escape sequence for a backslash.
L ? ? ? A a . , : / $ < > | \
52
In the example below, the Mask is "\####", which produces a literal "#" pound sign and three numeric characters. If "123" is typed in to the masked edit, you will see "#123".
To get the input for a RadMaskedEditBox, use the Value property. In this case the Value property is "123" and the Text property is "#123".
Numeric Masks
If the mask type is "Numeric" another set of masks applies and the mask can be followed by a precision specifier. By default, these numbers will be formatted as defined by CultureInfo.CurrentCulture.NumberFormat. When the mask is "Numeric", the user can increment and decrement using the up and down arrow keys.
53
54
Format Pattern Description dd ddd M MM MMM MMMM y yy yyy h hh H HH m mm The numeric day of the month. The abbreviated name of the day of the week. The month name followed by the numeric day. The numeric month. The abbreviated name of the month. The full name of the month. The full month name and year numeric. The year without the century. The year in four digits, including the century. The hour in a 12-hour clock. The hour in a 12-hour clock. The hour in a 24-hour clock. The hour in a 24-hour clock. The minute. The minute.
55
Here are several examples that show the RadMaskedEditBox in action along with the Value property expressed using ToString() and the Mask:
Other Properties
Culture: This property allows you to set the current language and culture from a drop down list at designtime or assign a new CultureInfo instance at run-time. For example, you can assign the culture code for Chinese: [VB] Setting the Culture meDemo.Mask = "D" meDemo.Culture = New CultureInfo("zh-CN") [C#] Setting the Culture meDemo.Mask = "D"; meDemo.Culture = new CultureInfo("zh-CN"); ...and this results in the RadEditor looking something like this example:
PromptChar: This property represents the character displayed in any blank space defined by a Mask character. By default the character is an underscore "_".
56
57
Format
The Format property of the date time picker can be Long, Short, Time and Custom. These settings control date or time representation in the text portion of the control. If you set the Format to Custom, you can also set the CustomFormat property. The code example below displayssomething like: "2008 December 30 11:45:56 AM". [VB] Assigning Format and CustomFormat Properties radDateTimePicker1.Format = DateTimePickerFormat.[Custom] radDateTimePicker1.CustomFormat = "yyyy MMMM dd h:m:s tt" [C#] Assigning Format and CustomFormat Properties radDateTimePicker1.Format = DateTimePickerFormat.Custom; radDateTimePicker1.CustomFormat = "yyyy MMMM dd h:m:s tt"; See the Masked Edit Box "Date Time Formats" section for a complete list of characters that can be used in the CustomFormat property.
Internationalization
Like the RadMaskedEditBox in DateTime mode, RadDatePicker also has internationalization support. [VB] Assigning the Culture radDateTimePicker1.Culture = New CultureInfo("zh-CN") [C#] Assigning the Culture radDateTimePicker1.Culture = new CultureInfo("zh-CN");
58
To get or set the check mark for the checkbox, use the Checked property. To access events for the checkbox, currentlyyou need to drill down to the embedded RadCheckBoxElement and subscribe to its events. The example below navigates through the DateTimePickerElement to locate the RadCheckBoxElement. [VB] Handling the ToggleStateChanged Event of the Date Time Picker Checkbox Dim checkBox As RadCheckBoxElement = TryCast (Me.radDateTimePicker1.DateTimePickerElement.Children(1).Children(0), RadCheckBoxElement) checkBox.ToggleStateChanged += New StateChangedEventHandler(checkBox_ToggleStateChanged) '... Sub checkBox_ToggleStateChanged(sender As Object, args As StateChangedEventArgs) RadMessageBox.Show(args.ToggleState.ToString()) End Sub [C#] Handling the ToggleStateChanged Event of the Date Time Picker Checkbox RadCheckBoxElement checkBox = radDateTimePicker1.DateTimePickerElement.Children[1].Children [0] as RadCheckBoxElement; checkBox.ToggleStateChanged += new StateChangedEventHandler(checkBox_ToggleStateChanged); //... void checkBox_ToggleStateChanged(object sender, StateChangedEventArgs args) { RadMessageBox.Show(args.ToggleState.ToString()); } How could you have found the checkbox element on your own? You can find this element using the Edit UI Elements link from the Smart Tag. In the screen shot below, trace the hierarchy starting with the RootRadElement... 1. radDateTimePicker1.DateTimePickerElement 2. radDateTimePicker1.DateTimePickerElement.Children[1] (gets us to DockLayoutPanel) 3. radDateTimePicker1.DateTimePickerElement.Children[1].Children[0] (under DockLayoutPanel, the first child is RadCheckBoxElement).
59
You can also enable the ShowUpDown property to make the date picker more like a RadMaskedEditBox in DateTime mode. When ShowUpDown is true, the calendar does not appear, but you can page through the selected part of the date time string. For instance, if you have the AM/PM designator selected, the arrow will toggle between AM and PM. You can find the complete source for this project at: \Editors\<VB|CS>\EditorsOverview
60
61
Spin Editor
RadSpinEditor is a themeable alternative to the standard Windows Numeric Up Down control. It allows users to edit a number in a textbox by using up and down buttons.
To use the RadSpinEditor set or retrieve the Value property. Use the Minimum and Maximum properties to limit the upper and lower bounds that a value may be set to. The other unique properties of RadSpinEditor are...
InterceptArrowKeys: This property when true (the default) allows the user to press the UP ARROW and DOWN ARROW keys to select values. The focus must be on the control for this functionality to work. ReadOnly: This property when true prevents direct text entry and allows the text values to be changed through the up and down arrows only. By default this property is turned off. RightToLeft: If this property is set to Yes the arrow buttons are displayed on the left, text on the right. Increment: The amount incremented or decremented when the user clicks the up or down arrow buttons. By default this value is "1". ThousandsSeparator: This property when true displays a thousands separator. By default this property is
62
DecimalPlaces: Gets or sets the number of decimal places to display in the RadSpinEdit.
Events
The ValueChanging event fires before the value has changed and allows you to prevent a given value from being entered. The event passes a ValueChangingEventArgs parameter that includes the OldValue, NewValue and Cancel properties. Set Cancel true to prevent the change in NewValue. The example below stops the value from changing if the new value is greater than twice the size of the old value. [VB] Handling the ValueChanging Event Private Sub radSpinEditor1_ValueChanging(sender As Object, e As ValueChangingEventArgs) e.Cancel = Convert.ToDecimal(e.NewValue) > Convert.ToDecimal(e.OldValue) * 2 End Sub [C#] Handling the ValueChanging Event private void radSpinEditor1_ValueChanging(object sender, ValueChangingEventArgs e) { e.Cancel = Convert.ToDecimal(e.NewValue) > Convert.ToDecimal(e.OldValue) * 2; } Once the value has changed you can handle the ValueChanged event. In the example below the Value is assigned to a label and to a progress bar.
[VB] Handling the ValueChanged Event Private Sub radSpinEditor1_ValueChanged(sender As Object, e As EventArgs) lblSpin.Text = radSpinEditor1.Value.ToString() radProgressBar1.Value1 = DirectCast(radSpinEditor1.Value, Integer) End Sub [C#] Handling the ValueChanged Event private void radSpinEditor1_ValueChanged(object sender, EventArgs e) Handles radSpinEditor1.ValueChanged { lblSpin.Text = radSpinEditor1.Value.ToString(); radProgressBar1.Value1 = (int)radSpinEditor1.Value; } You can find the complete source for this project at: \Editors\<VB|CS>\EditorsOverview
63
Color Dialog
RadColorDialog is a CommonDialog descendant and replaces the standard ColorDialog. The RadColorDialog offers a high degree of configurability compared to its standard counterpart. There are tabs for "Basic", "System", "Web" and "Professional" color selection. See the screenshots below for examples.
Basic lets you choose a predefined color from a honeycomb interface where you click a colored cell to choose the color.
64
System lets you choose one of the System.Drawing.SystemColors enumeration from a list. Each is a color of a Windows display element (i.e. ButtonShadow, ActiveCaptionText, etc).
Web lets you choose one of the named web colors from a list.
65
Using RadColorDialog
To use the RadColorDialog, call its ShowDialog() method. If the returned DialogResult value is "OK", retrieve the SelectedColor property: [VB] Using RadColorDialog ShowDialog() Private Sub btnChangeColor_Click(sender As Object, e As EventArgs) radColorDialog1.SelectedColor = pnlColor.BackColor If radColorDialog1.ShowDialog() = DialogResult.OK Then pnlColor.BackColor = radColorDialog1.SelectedColor End If End Sub [C#] Using RadColorDialog ShowDialog() private void btnChangeColor_Click(object sender, EventArgs e) Handles btnChangeColor.Click { radColorDialog1.SelectedColor = pnlColor.BackColor; if (radColorDialog1.ShowDialog() == DialogResult.OK) { pnlColor.BackColor = radColorDialog1.SelectedColor; } } RadColorDialog also has a Reset() method that resets the dialog properties to default values, including replacing the underlaying ColorDialogForm with a new instance. RadColorDialoghas properties for setting and retrieving color and for getting at properties used to configure the dialog:
SelectedColor:A standard Color type. SelectedHslColor:A HslColor type where HSL stands for Hue, Saturation and Luminence. CustomColors[]: This is a read-only array of Color types. You can query the contents of the custom colors
66
While RadColorDialog only has these few properties, the color dialog is configured through the ColorDialogForm.
RadColorDialogForm
The significant properties unique to RadColorDialogForm are:
ShowBasicColors, ShowSystemColors, ShowWebColors, ShowProfessionalColors: If true (the default) the corresponding Basic, System, Web and Professional tabs are displayed. ActiveMode: Determines the currently selected tab. Valid enumeration values from Telerik.WinControls.ColorPickerActiveMode are Basic, System, Web, Professional. AllowColorPickFromScreen: When true (the default) the "eye dropper" tool is displayed. AllowColorSaving: Toggles the "Add a custom color" button visibility. BackColor: The background color of the color selector as a whole. You can also set this color to be Transparent to have it blend in with other UI elements. ForeColor: The color for labels and text entry. SelectedColor:The color swatch labeled "New". OldColor: The color swatch labeled "Current". AllowEditHEXValue: If true (the default) enables hexadecimal entry of color values. ShowHEXColorValue: If true (the default) displays the hexadecimal entry of color values. ShowCustomColors: If true displays custom colors boxes along the bottom of the dialog.
To localize or otherwise customize the text in the dialog, use properties AddNewColorButtonText, BasicTabHeading, SystemTabHeading, WebTabHeading, ProfessionalTabHeading, SelectedColorLabelHeading and OldColorLabelHeading. You can find the complete source for this project at: \Editors\<VB|CS>\EditorsOverview
67
68
69
EditorsInput Walkthrough
This walk through will use the "ColorDialogWalkthrough" project as a basis andwill gather input data from the form and display it in a message box. You can find the complete source for this project at: \Editors\<VB|CS>\EditorsInputWalkthrough 1. Start with the "ColorDialogWalkthrough" project or a copy. 2. Add a static helper function GetKnownColorName() to retrieve a readable name for a given color. This function should be added to the Utils.cs file. Remember that we only allowed system and web colors to be selected from the color dialog, so all the colors will have proper names, not just hex values strings. The method iterates the KnownColor enumeration and tries to match the rgb value against the color passed in. [VB] Define the GetKnownColorName() Method Public Shared Function GetKnownColorName(color As Color) As String For Each knownColor As KnownColor In [Enum].GetValues(GetType(KnownColor)) If color.ToArgb() = Color.FromKnownColor(knownColor).ToArgb() Then Return Color.FromKnownColor(knownColor).Name End If Next Return [String].Empty End Function [C#] Define the GetKnownColorName() Method
70
Enabled On a group box A textbox base, date time picker or RadButton. [VB] Defining the IsEditorControl Method Private Function IsEditorControl(control As Control) As Boolean If Not control.Enabled Then Return False End If ' only get input from controls within a groupbox If Not (TypeOf control.Parent Is GroupBox) Then Return False End If Return TypeOf control Is RadTextBoxBase OrElse TypeOf control Is RadDateTimePicker OrElse TypeOf control Is RadButton End Function [C#] Defining the IsEditorControl Method private bool IsEditorControl(Control control) { if (!control.Enabled) return false; // only get input from controls within a groupbox if (!(control.Parent is GroupBox)) return false; return control is RadTextBoxBase || control is RadDateTimePicker || control is RadButton; }
4. Add another helper method GetControlValue() that takes a RadControl and returns the appropriate value object for that control. Notice that when we get to the"Choose Wrap Color" button we drill down to it's fill primitive and get the background color. The value in this case is the known color name of the button background. Also notice that there are only two RadButtons on the form, but the "Place Order" button is not parented by a GroupBox and so is ignored by IsEditorControl() method. [VB] Defining the GetControlValue Method
71
72
73
Tool Tips
The most flexible way to display tool tips in your edit controls is to handle the ToolTipTextNeeded event. The ToolTipTextNeedeEventArgs have a single property ToolTipText that can be assigned to.
You can find the complete source for this project at: \Editors\<VB|CS>\ToolTipsWalkthrough 1. Start with the "EditorsInputWalkthrough" project or a copy. 2. Select the "Name" RadTextBox. In the Properties window Event tab, locate the ToolTipTextNeeded event. Type in "HandleToolTipTextNeeded" and click Enter to create an event handler. 3. Add the code below to the event handler. [VB] Handling the ToolTipTextNeeded Event Private Sub HandleToolTipTextNeeded(sender As Object, e As ToolTipTextNeededEventArgs) e.ToolTipText = "Please enter " + (TryCast(sender, RadItem)).ElementTree.Control.Tag.ToString() End Sub [C#] Handling the ToolTipTextNeeded Event private void HandleToolTipTextNeeded(object sender, ToolTipTextNeededEventArgs e)
74
4. Assign this same event handler to all the editors on the form. 5. Click Ctl-F5 to run the application. Move the mouse over each of the editors to see the tool tip.
Validation
All of the RadControls based editors work nicely with the built-in Microsoft validation mechanisms. One way we can handle validation is to add a standard Microsoft ErrorProvidercomponent and subscribe to the editcontrol's Validating event. This fires when the user tabs off the control. If the input is invalid we can use the
75
[VB] Handling the Validating Event with Cancel Private Sub tbName_Validating(sender As Object, e As CancelEventArgs) If (TryCast(sender, RadTextBox)).Text.Equals([String].Empty) Then errorProvider1.SetError(TryCast(sender, Control), "Please enter a valid name") e.Cancel = True End If End Sub [C#] Handling the Validating Event with Cancel private void tbName_Validating(object sender, CancelEventArgs e) { if ((sender as RadTextBox).Text.Equals(String.Empty)) { errorProvider1.SetError(sender as Control, "Please enter a valid name"); e.Cancel = true; } } This route is workable but a bit restrictive of the users ability to move around the form at will and enter data in any order. We can loosen this restriction a bit by not setting Cancel. This next example validates the delivery date time picker to verify the selected date is a weekday but does not set Cancel true. The error icon is still shown, but the user is not prevented from performing other actions on the form. [VB] Handling the Validating Event handler ' validate the date time picker to allow only weekday dates Private Sub dtDeliver_Validating(sender As Object, e As CancelEventArgs) Dim [error] As String = Nothing If Utils.IsWeekend((TryCast(sender, RadDateTimePicker)).Value) Then [error] = "Please enter a weekday date for " + (TryCast(sender, Control)).Tag.ToString() End If errorProvider1.SetError(DirectCast(sender, Control), [error]) End Sub [C#] Handling the Validating Event handler // validate the date time picker to allow only weekday dates private void dtDeliver_Validating(object sender, CancelEventArgs e) { string error = null; if (Utils.IsWeekend((sender as RadDateTimePicker).Value)) { error = "Please enter a weekday date for " + (sender as Control).Tag.ToString(); } errorProvider1.SetError((Control)sender, error); } When some completion action is about to take place (e.g. saving data), the data should be valid at that time.Extend the "EditorsInputWalkthrough" project to include a validity check when the "Place Order" button is
76
First clears any existing errors using the ErrorProvider Checks if a control is one we've defined as an "Editor control". If it's an editor control then we retrieve the control value. If the value is a DateTime type, validity checking consists of making sure the value is a weekend. If the value is a string, then the string must not be empty. If the value is not valid, the ErrorProvider SetError() method is called. Even if the control is not an editor,the method recurses if there are child controls. [VB] Defining the ValidateControls() Method Private Function ValidateControls(controls As Control.ControlCollection) As Boolean Dim isValid As Boolean = True For Each control As Control In controls ' clear old errors errorProvider1.SetError(control, "") If IsEditorControl(control) Then Dim value As Object = GetControlValue(TryCast(control, RadControl)) If (TypeOf value Is DateTime) AndAlso (Utils.IsWeekend(DirectCast(value, DateTime))) errorProvider1.SetError(control, "Please enter a weekday date to " + control.Tag.ToString()) isValid = False ElseIf value.ToString().Equals([String].Empty) Then errorProvider1.SetError(control, "Please enter " + control.Tag.ToString()) isValid = False End If End If ' recurse into child controls of this control ' so that we get items on the group panels. If control.Controls.Count > 0 Then If Not ValidateControls(control.Controls) Then isValid = False End If End If Next Return isValid End Function [C#] Defining the ValidateControls() Method private bool ValidateControls(Control.ControlCollection controls) { bool isValid = true; foreach (Control control in controls)
77
78
4.6 Summary
This chapter explained how to retrieve information from the user with the RadSpinEditor, RadDateTimePicker, RadMaskedEditBox, RadTextBox and RadColorDialog controls. The chapter began with a brief exploration of basic usability for each control and highlights special features. The chapter included explanation how to implement tool tips, validate user entry and control specific information on edit masks, date formats and internationalization support.
79
RichTextBox Beta
5.1 Overview
RadRichTextBox is a control that is able to display and edit rich-text content including formatted text arranged in pages, paragraphs, spans (runs), etc.
Rich Text Formatting - Telerik RadRichTextBox control allows you to edit text and apply rich formatting options, like:
Bold, Italic Underline, Strike Through Text color and background Bullet and numbered lists Paragraph alignment and indentation Show/Hide formatting symbols Clear Formatting
Inserting pictures/symbols SpellChecker - extensible spell checking for different languages, using built-in or custom dictionaries. Multi-level Undo/Redo Support - Telerik RadRichTextBox provides desktop-like usability and control thanks to its multilevel Undo/Redo feature. It allows past actions to be reviewed and reversed, just like in Microsoft Word. Two types of layout Paged and Flow (as text in an HTML page viewed in a browser). Multi-region selection - the built-in multi-region support enables you to perform various operations for more than one selection simultaneously. Import/export - with Telerik RadRichTextBox control you can load XAML, HTML, RTF, DocX (rich-text) or
80
5.2 F.A.Q
How to Get and Set the Text of RadRichTextBox
RadRichTextBox does not have a Text property because different formats for import and export of documents are supported RTF, HTML, XAML, docX, plain text and PDF (export only). In order to set the contents of the document, it should be clear what format the data is in. For easier extensibility and separation of concerns, format providers that deal with the import and export of the documents are used. Here is a list of the currently available format providers and the assemblies they are included in:
TxtFormatProvider (plain text) Telerik.WinControls.RichTextBox.FormatProviders.Txt; DocxFormatProvider - Telerik.WinControls.RichTextBoc.FileFormats.OpenXml.Docx; HtmlFormatProvider - Telerik.WinControls.RichTextBox.FileFormats.Html; XamlFormatProvider - Telerik.WinControls.RichTextBox.FileFormats.Xaml; RtfFormatProvider Telerik.WinControls.RichTextBox.FileFormats.Rtf; PdfFormatProvider - Telerik.WinControls.RichTextBox.FileFormats.Pdf.
You can read more about the use of format providers here. Overall, what you need to do to get the content of the document in a specific format is to create an instance of the corresponding provider and export the document. An example is illustrated below: [C#] Export XAML file public string GetXAML(RadDocument document) { XamlFormatProvider provider = new XamlFormatProvider(); return provider.Export(document); } [VB.NET] Export XAML file Public Function GetXAML(ByVal document As RadDocument) As String Dim provider As New XamlFormatProvider() Return provider.Export(document) End Function To get the text stripped of all formatting, you can useTxtFormatProvider. Setting the content of RadRichTextBox can be done in the same manner, if you have the content in one of these formats. For example, importing an HTML string in the document of a RadRichTextBox can be done as follows: [C#] Load HTML file public RadDocument ImportHtml(string content) { HtmlFormatProvider provider = new HtmlFormatProvider(); return provider.Import(content); } [VB.NET] Load HTML file Public Function ImportHtml(ByVal content As String) As RadDocument Dim provider As New HtmlFormatProvider() Return provider.Import(content) End Function
81
82
As you can see the text is still editable. To make it read only you have to set theIsReadOnlyproperty of the RadRichTextBox toTrue. [C#] Read only mode radRichTextBox1.IsReadOnly = true; [VB.NET] Read only mode RadRichTextBox1.IsReadOnly = True
83
84
Design-Time Documents
You are able to predefine the content of the RadRichTextBox at design time. This means that the RadRichTextBox can be used to display static rich content. Defining such a content can be done via the following UI Elements:
RadRichTextBox API
Instead of visualizing a static rich content, you may want to use the RadRichTextBox as an input control. In this case, in order to provide the user with the ability to format the inputted content, you have to provide a UI that communicates with the RadRichTextBox. For that purpose the RadRichTextBox exposes an API, which contains various methods that can apply different formatting to the inputted content. To learn more about the API methods read this topic. To see an example of a RadRichTextBox that allows to apply bold, italic and underline formatting, take a look at this topic.
Scrolling
When the available size for the control becomes less than the size of the content, the RadRichTextBox will automatically display horizontal or vertical scrollbars respectively.
Current Span
TheCurrentEditingStyleproperty returns an instance of theStyleDefinitionclass, which allows you to get information abou the current element. You can combine the usage of this property with the usage of
85
Paged
When using the paged mode, the content of the edited document is divided into pages. The size and layout of each page are defined by theDefaultPageLayoutSettingsproperty of theRadDocumentand more specifically theWidthandHeightproperties of thePageLayoutSettingsobject. Next, the margins of the control in a page are specified by thePageMarginproperty of eachSection. Since several sections can appear on a single page, the margin properties of the firstSectionthat appears on a certain page would be valid. InPagemode, resizing a RadRichTextBox will not affect the document layout but scrollbars will appear if the document does not fit in the view.
86
FlowNoWrap
TheFlowNoWraplayout mode is similar to theFlowlayout mode, but it doesn't allow the text in the separate paragraphs to get wrapped when the free space gets exceeded. Instead a horizontal scroll bar will appear.
5.6 Selection
The RadRichTextBox supports not only selection via the UI, but also programmatic selection. This topic will explain you how to:
UI Selection
The user is able to select the content of the RadRichTextBox in the same way as in MS Word. This is done by clicking on the desired position and dragging to the desired end of the selection. A multiple ranges selection is also allowed. This one is done by holding theCtrlkey while selecting the different ranges.
Programmatic Selection
The developer is allowed to work with the selection programmatically. This can be used when having aFindfunctionality in your RadRichtextBox and you want to select the found string. Examples that involve the programmatic selection can be found in the How To section. The programmatic selection gets implemented via theDocumentSelectionclass. The instance of the class gets associated with theRadDocumentof the RadRichTextBox and allows you to specify selection starts and ends, selection ranges and other. You can manage the selection by either using theSelectionproperty of theRadDocumentor by creating an instance of theDocumentSelectionclass. Here is an example of how to select the current word. To learn more about theDocumentPositionread the Positioning topic. [C#] Select the current word DocumentPosition startPosition = this.radRichTextBox1.Document.CaretPosition; //new DocumentPosition( this.radRichTextBox.Document ); DocumentPosition endPosition = new DocumentPosition(startPosition); startPosition.MoveToCurrentWordStart(); endPosition.MoveToCurrentWordEnd(); this.radRichTextBox1.Document.Selection.AddSelectionStart(startPosition); this.radRichTextBox1.Document.Selection.AddSelectionEnd(endPosition); [VB.NET] Select the current word Dim startPosition As DocumentPosition = Me.RadRichTextBox1.Document.CaretPosition 'new DocumentPosition( this.radRichTextBox.Document ); Dim endPosition As New DocumentPosition(startPosition) startPosition.MoveToCurrentWordStart() endPosition.MoveToCurrentWordEnd() Me.RadRichTextBox1.Document.Selection.AddSelectionStart(startPosition) Me.RadRichTextBox1.Document.Selection.AddSelectionEnd(endPosition)
87
5.7 Search
RadRichTextBox supports searching the contents of the document along with providing some methods for manipulating the selection. Used in combination, they become quite a powerful tool enabling scenarios like highlighting of specific parts of the document or replacing words and collocations. To learn more about the selection API read theSelection (Section 5.6)topic. The simplest scenario finding a string in the content of the document can be implemented with the following code: [C#] Select all matches private void SelectAllMatches(string toSearch) { this.radRichTextBox1.Document.Selection.Clear(); // this clears the selection before
88
89
90
5.8 Positioning
The positioning feature in the RadRichTextBox is used to navigate through document's content and to get information about the document's elements at a specific position. TheRadDocumentuses the positioning to track the movement of the caret and to control the selection. The positioning is implemented via theDocumentPositionclass. This class can be used by the developer to programmatically control the positioning or the selection.DocumentPositionoffers methods, such asMoveToNextWord(),MoveToPreviousWord(),MoveToCurrentLineStart/End()and so on, which will navigate to the given document element. In order to get information about the element at a given position you can use several methods such asGetCurrentSpanBox(),GetCurrentParagraphBox(),GetCurrentSectionBox()and so on. DocumentPositionalso redefines equality and comparison operators for more convenience, when you should find whether theDocumentPositionis before or after another position in the natural flow of the document. By default RadRichTextBox movesDocument.CaretPositionusing arrow keys or on mouse click.DocumentPositioncan also be obtained by giving the coordinates of a point in the document using the methodDocumentPosition.SetPosition. You can manage the caret position for a specificRadDocumentby either accessing itsCaretPositionproperty, which is of typeDocumentPosition, or by creating a new instance of theDocumentPositionclass and associating it with the desiredRadDocument. When using theCaretPositionproperty you are directly managing the caret position in theRadDocument. By using theDocumentPositionclass you can create instances of several positions inside the document without changing the current caret position.
CaretPosition property
Here is an example of how to use theCaretPositionproperty to get the current word. [C#] string currentSpanText = this.radRichTextBox1.Document.CaretPosition.GetCurrentSpanBox ().Text; [VB.NET] Dim currentSpanText As String = Me.RadRichTextBox1.Document.CaretPosition.GetCurrentSpanBox ().Text
91
DocumentPosition class
An alternative of using theCaretPositionproperty is to create an instance of theDocumentPositionclass. Here is the same example from the previous chapter done with an instance of theDocumentPositionclass. [C#] DocumentPosition position = new DocumentPosition(this.radRichTextBox1.Document); string currentSpanText1 = position.GetCurrentSpanBox().Text; [VB.NET] Dim position As DocumentPosition = New DocumentPosition(Me.RadRichTextBox1.Document) Dim currentSpanText1 As String = position.GetCurrentSpanBox().Text
5.9 History
The RadRichTextBox supports not only selection via the UI, but also programmatic selection. This topic will explain you how to:
Enable/Disable History
You can enable or disable the history for theRadDocumentvia theEnabledproperty of theDocumentHistory. [C#] Enable history this.radRichTextBox1.Document.History.Enabled = true; [VB.NET] Enable history Me.RadRichTextBox1.Document.History.Enabled = False
Clear History
To clear the history you just have to call theClear()method of theDocumentHistoryclass. [C#] Clear history this.radRichTextBox1.Document.History.Clear(); [VB.NET] Clear history Me.RadRichTextBox1.Document.History.Clear()
Undo/Redo
To undo and redo some actions, you can call theUndo()andRedo()methods of the RadRichTextBox. [C#] Undo/Redo history this.radRichTextBox1.Undo(); this.radRichTextBox1.Redo(); [VB.NET] Undo/Redo history Me.RadRichTextBox1.Undo() Me.RadRichTextBox1.Redo()
92
5.10 ReadOnly
To make the RadRichTextBox read only, you have to set itsIsReadOnlyproperty toTrue. [C#] Read only mode radRichTextBox1.IsReadOnly = true; [VB.NET] Read only mode RadRichTextBox1.IsReadOnly = True Except theReadOnlyproperty, there are several other properties that can be used to control the response of the RadRichTextBox towards the user actions against it:
Enabled- setting this property toFalsewill disable the entire control. The user won't be able to enter any input in it and to scroll the contents. IsSelectionEnabled- setting this property toFalsewill disable the user to perform any selection inside the RadRichTextBox control.
93
XAML- to import/exportXAMLdocuments you have to use theXamlFormatProviderclass. DOCX- to import/exportDOCXdocuments you have to use theDocxFormatProviderclass. HTML- to import/exportHTMLdocuments you have to use theHtmlFormatProviderclass. RTF- to import/exportRTFdocuments you have to use theRtfFormatProviderclass. Plain text- to import/export plain text documents you have to use theTxtFormatProviderclass. PDF- to export documents toPDFyou have to use thePdfFormatProviderclass.
Here are some examples on how to export and import. The "Export to String" and "Import from String" examples are only valid for the text-based format providers (Html, Xaml, Rtf and TxtFormatProvider). The "Export to File" and "Import from File" are applicable to each of the format providers (save for PDF import). To use them with the desired format just replace the format provider and change the settings of theSaveFileDialogor theOpenFileDialog. Export to String [C#] Export to String public string ExportToXAML(RadDocument document) { XamlFormatProvider provider = new XamlFormatProvider(); return provider.Export(document); } [VB.NET] Export to String Public Function ExportToXAML(ByVal document As RadDocument) As String Dim provider As New XamlFormatProvider() Return provider.Export(document) End Function Export to File [C#] Export to File public void ExportToDocx(RadDocument document) { DocxFormatProvider provider = new DocxFormatProvider(); SaveFileDialog saveDialog = new SaveFileDialog(); saveDialog.DefaultExt = ".docx"; saveDialog.Filter = "Documents|*.docx"; DialogResult dialogResult = saveDialog.ShowDialog(); if (dialogResult == System.Windows.Forms.DialogResult.OK) { using (Stream output = saveDialog.OpenFile())
94
95
Import/Export settings
As sometimes the formats may support several ways for presenting one and the same content, some customization options have been provided in order to specify the result which the user expects. This is achieved with the help of import and export settings, which some format providers expose (HtmlFormatProviderandPdfFormatProvider). You need to create an instance of the settings and assign it to the property of the provider you will be using. Then, you can set (or retrieve) the properties you need.HtmlFormatProvidermakes use ofHtmlExportSettingsandHtmlImportSettingsto control import/export. 1. HtmlExportSettingsprovides the following options:
DocumentExportLevel you can choose betweenDocumentandFragment.Documentis the default value, which includes the HTML declaration, the<HTML>,<TITLE>,<HEAD>and<BODY>tags, whereas setting the document export level toFragmentresults in exporting the content of the<BODY>tag only. StylesExportMode the options here areInlineandClasses, the default one beingClasses. Predefined classes is the preferred way for setting styles, yet inline styles may be useful with regard to the consumer of the HTML. For instance, in order to use the exported HTML inTelerik Reporting, theStylesExportModeneeds to be set toInline. ImageExportMode the user can choose between several options or even provide his own implementation by choosing theImageExportingEventoption for theImageExportModeproperty and handling theImageExportingEvent. TheUriSourceoption can be used if you want to export an image by setting itssrcproperty to theURLrather than having the raw data in the exported document.
UseDefaultStylesheetForFontProperties aBooleanproperty indicating whether the default font properties of RadRichTextBox or the defaults in the HTML specification should be used for the elements that do not set theirFontSize,FontFamily,FontWeightandFontStyleexplicitly. LoadImageFromUrlevent this event was introduced at a time whenHtmlFormatProviderdid not automatically load images from URLs. The feature is currently supported out of the box, but this event can be useful if using virtual directories and files on the server.
96
ContentsCompressionMode this property allows you to choose if you wish to make use of compression (by setting it toDeflateorAutomatic) or not (PdfContentsCompressionMode.None) of the text content of the document. ContentsDeflaterCompressionLevel an integer between -1 and 9, used to get or set the compression level to be used when deflating the content of the document. Default Compression is-1, No Compression is0and Best Compression is9; ImagesCompressionMode the user can choose betweenNone,Jpeg(supported only for images, imported as JPEG), Deflate (the deflate algorithm will be applied to compress the images) orAutomatic(the best algorithm will be automatically decided upon for you). ImagesDeflaterCompressionLevel same asContentsDeflaterCompressionLevel, but applied to the images in the document. This property is respected when an image is compressed withDeflate.
PDF importis currentlynotsupported, so there are not any import settings. There are not anyImportorExportSettingsforXAMLeither, as theXAMLserialization is lossless and all elements are imported and exported as they would appear if declared in aXAMLpage in the application. DocxFormatProviderdoes not currently provide any settings as the document content is matched as closely as possible to the Word document.
Importing
When theHtmlFormatProviderimports anHTMLdocument, it parses it and converts the HTML element tree toRadDocument. Importing is basically made up of two parts content and styling.
Content
HTML content is mapped to several types ofRadDocumentelements paragraphs, spans and tables. Tags mapped to paragraphs are:
97
formatting tags, <span>, <font> Additionally, line breaks are inserted between consequent block elements (<div>).
Styling
Styling is supported through CSS styles (classes or inline) and a number of formatting tags (including<font>). Although the<font>tag has been deprecated, legacy software and markup requires support for it. Supported formatting tags are:
<b>, <strong> turn on bold <i>, <em> turn on italic <u> turn on underline <h1>through<h6> apply heading
text-align margin-left margin-right color background-color font-family font-size font-style font-weight text-decoration (underline, line-through) vertical-align (sub, super)
face equivalent to CSS propertyfont-family size equivalent to CSS propertyfont-size color equivalent to CSS propertycolor
Exporting
When exporting toHTML, theHtmlFormatProvideriterates through theRadDocumenttree and generatesHTMLnodes. It is designed to generate validXHTMLdocument in order to preserve the formatting as much as possible. Styles are exported as CSS classes in the head of the document and used through the body. The structure of theHTMLdocument closely resembles that ofRadDocument paragraphs and spans.
5.14 Spellcheck
The RadRichTextBox control is designed to support "spell checking as you type" by setting a single property and specifying a proper dictionary to it. This topic will explain you the following:
Enabling SpellCheck
To enable or disable the spell checking functionality (present as red wavy underlines below unrecognized
98
Dictionaries
The dictionaries in RadRichTextBox implement theIWordDictionaryinterface. Easy interoperability with dictionaries fromRadSpellfor ASP.NET is achieved through theWordDictionaryclass, which supports the loading of a dictionary directly from the*.tdffiles, used withRadSpell. Here is an example of aWordDictionaryloaded from aTDFfile. When adding aWordDictionaryor similar object use theAddDictionary(IWordDictionary dictionary, CultureInfo culture)method of theDocumentSpellChecker. You can also associate a dictionary with a specific culture. The method to remove this dictionary isRemoveDictionary(CultureInfo culture). The given example doesn't contain the logic used to read theTDFfile as aStream. [C#] Load dictionary private void LoadDictionary(Stream tdfFileStream) { WordDictionary dictionary = new WordDictionary(); dictionary.Load(tdfFileStream); ((DocumentSpellChecker)this.radRichTextBox1.SpellChecker).AddDictionary(dictionary, CultureInfo.InvariantCulture); } [VB.NET] Load dictionary Private Sub LoadDictionary(ByVal tdfFileStream As Stream) Dim dictionary As New WordDictionary() dictionary.Load(tdfFileStream) CType(Me.RadRichTextBox1.SpellChecker, DocumentSpellChecker).AddDictionary(dictionary, CultureInfo.InvariantCulture) End Sub
Adding a Word
To add a word to a dictionary you can either use theAddWord()method of theDocumentSpellCheckeror of the dictionary itself. Using the first one you can add a word to multiple dictionaries associated to the same culture. This done done by passing the desired culture as parameter to the method. Using the overload of theAddWord()method that takes only the word as argument is equal to using the second overload and passingCultureInfo.InvariantCultureas argument. Using theAddWord()method of the dictionary itself will add the word only to the respective dictionary. Here is an example: [C#] Add word to dictionary this.radRichTextBox1.SpellChecker.AddWord("RadRichTextBox", CultureInfo.InvariantCulture); [VB.NET] Add word to dictionary Me.RadRichTextBox1.SpellChecker.AddWord("RadRichTextBox", CultureInfo.InvariantCulture)
99
100
Ctrl+E, Ctrl+Shift+E
5.15 RibbonBar UI
RadRichTextBox control comes with a predefined number of shortcuts which trigger commands that allow you to manipulate the selected text the way you want. However, in many cases it is more convenient for the user to click buttons which execute these commands instead of pressing a shortcut key. The purpose of this article is to demonstrate how you can build user interface appropriate for the purposes of RadRichTextBox with the help of RadRibbonBar for WinForms. What is more, at the end of the article you will find a link to a project which implements a RadRibbonBar built according to the RadRichTextBox capabilities. You will also find a description of how you can bind this RadRibbonBar to an existing RadRichTextBox.
Building RadRibbonBar UI
Building the user interface of the RadRichTextBox-enabled is pretty simple. You can use thedesign-time capabilities (http://www.telerik.com/help/winforms/ribbonbar-getting-started.html)of RadRibbonBar to insert and arrange elements in it. The other option is toinsert elements through code (http://www.telerik.com/help/winforms/ribbonbar-programming-radribbonbar-adding-and-removing-tabsand-ribbonbar-groups.html). The following code snippet demonstrates how to insert a 'Home' tab, a 'Font' group and a button which toggles the bold mode of the text: [C#] public RichTextBoxRibbonUI() { InitializeComponent(); RibbonTab tabHome = new RibbonTab(); tabHome.Text = "Home"; this.radRibbonBar1.CommandTabs.Add(tabHome);
101
102
If there is a RichTextBox on one of the forms in the main project, these references should should already exist. 5. Build the downloaded project. The customized RadRibbonBar component should appear in your Toolbox. 6. Drag it from your Toolbox to your Form. 7. Set theAssociatedRichTextBoxproperty to the RadRichTextBox instance that will be controlled by the RadRibbonBar user interface. 8. Run your solution. 9. The commands that you trigger by using the RadRibbonBar interface will be applied to the text of the associtated RadRichTextBox instance. 10. The following properties will allow you to control the visibility of the tabs of the customized RadRibbonBar implementation: [C#] richRibbonBar1.ShowHomeTab = false; richRibbonBar1.ShowInsertTab = false; richRibbonBar1.ShowPageLayoutTab = false; richRibbonBar1.ShowViewTab = false; richRibbonBar1.ShowReviewTab = false; [VB.NET] richRibbonBar1.ShowHomeTab = False richRibbonBar1.ShowInsertTab = False richRibbonBar1.ShowPageLayoutTab = False richRibbonBar1.ShowViewTab = False richRibbonBar1.ShowReviewTab = False In case you are using RadRibbonForm, you can substitute the Telerik.WinControls.UI.RadRibbonBar type with TelerikEditor.RichRibbonBar type in the Designer code file of the RadRibbonForm. Feel free to add more properties that will be suitable for your scenario.
103
Menus
6.1 Objectives
Learn how to add drop-downand context menus to your application using RadMenu, RadContextMenu and RadContextMenuManager controls. Learnhow to build menus at design-time using the Menu Designer. Learn common programmatic tasks such as adding and removing menu items,locating and modifying menu items. Learnhow to programmatically pop up up a context menu in a specific screen location. Become familiar with the RadRibbonBar and RadApplicationMenu controls.
6.2 Introduction
Telerik has an array of flexible menuing options that help structure user choices within your application:
RadMenu enables you to implement attractive navigation systems, comprised of classic or Office 2007-style menus. Based on the Telerik Presentation Foundation, the component gives you full control over item appearance, orientation, and text-wrapping, while allowing you to easily nest checkboxes, images, or any other controls in design-time.
The same RadMenu functionality is available anywhere in the form using RadContextMenu. Context menus can be associated with specific controls or popped up programmatically at any X/Y location.
RadRibbonBar combines the functions of menus, tab strips and toolbars to make an interface similar to those introduced in Microsoft Office 2007. With RadRibbonBar you can organize all of the functionality of your application into a single compact ribbon.
104
RadApplicationMenu is the Telerik counterpart of the "application menu" that displays controls used to perform actions on entire documents and forms, such as Save and Print.
105
3. Add a RadMenu control to the form. Set the ThemeName property of the menu to "Office2007Silver". Set the ImageList property to point to the ImageList you added to the form. 4. Add a standard WinFormsRichTextBox control to the form. Set the Name property to "tbContent". Size the RichTextBox within the available area on the form and set the Anchor property to "Top, Bottom, Left, Right". Also set the HideSelection property to False and ShowSelectionMargin property to True. 5. In the RadMenu designer, click the "Type Here" prompt and enter "File". Repeat this step to create more top level menu items "Edit", "Format" and "Help". 6. Under the top level "File" menu item, click the "Add New" prompt and add a RadMenuItem. Set the name to "miNew", Text to "New" and the ImageKey to the image list image key representing "new". Add the "File" menu items:
Name = "miNew", Text = "New", ImageKey = <image for New>, TextImageRelation= ImageBeforeText Name = "miOpen", Text = "Open", ImageKey = <image for Open>, TextImageRelation= ImageBeforeText Name = "miSave", Text = "Save", ImageKey = <image for Save>, TextImageRelation= ImageBeforeText Add a RadMenuSeparatorItem. Name = "miQuit", Text = "Quit", TextImageRelation= ImageBeforeText
Name = "miCut", Text = "Cut", ImageKey = <image for Cut>, TextImageRelation= ImageBeforeText Name = "miCopy", Text = "Copy", ImageKey = <image for Copy>, TextImageRelation= ImageBeforeText Name = "miPaste", Text = "Paste", ImageKey = <image for Paste>, TextImageRelation= ImageBeforeText
Name = "miBold", Text = "Bold", ImageKey = <image for Bold>, CheckOnClick = True, TextImageRelation= ImageBeforeText Name = "miItalic", Text = "Italic", ImageKey = <image for Italic>, CheckOnClick = True, TextImageRelation= ImageBeforeText
Name = "miAbout", Text = "About", ImageKey = <image for About>, TextImageRelation= ImageBeforeText
10. Press Ctl-F5 to run the application and see what the menu looks like so far.
106
11. Double-click the "New" menu item and add the following code to the Click event handler: [VB] Handling the Menu Item Click Event Private Sub miNew_Click(sender As Object, e As EventArgs) tbContent.Clear() End Sub [C#] Handling the Menu Item Click Event private void miNew_Click(object sender, EventArgs e) { tbContent.Clear(); } 12. Double click each menu item except for the "Bold" and "Italic"items and add thecorresponding event handlers below: [VB] Handling the Menu Item Click Events Private Sub miOpen_Click(sender As Object, e As EventArgs) If openFileDialog1.ShowDialog() = DialogResult.OK Then tbContent.LoadFile(openFileDialog1.FileName, RichTextBoxStreamType.RichText) End If End Sub Private Sub miSave_Click(sender As Object, e As EventArgs) If saveFileDialog1.ShowDialog() = DialogResult.OK Then tbContent.SaveFile(saveFileDialog1.FileName, RichTextBoxStreamType.RichText) End If End Sub Private Sub miAbout_Click(sender As Object, e As EventArgs) RadMessageBox.SetThemeName(Me.ThemeName) RadMessageBox.Show(" By " + Environment.UserName + ", " + DateTime.Today.ToLongDateString (), "About RadMenu Demo") End Sub Private Sub miCut_Click(sender As Object, e As EventArgs) tbContent.Cut() End Sub
107
108
109
Tasks
From the Smart Tag Tasks menu you can Open Theme Builder to style all aspects of your control, select New Theme Manager to add a RadThemeManager component to the component tray, Edit Items to display the RadItem Collection Editor,Edit UI elements to browse all of the elements of the menu and to change properties for any element. The Theme Name drop down lets you pick an existing theme to style your control.
Learning center
The Learning center lets you navigate to a web browser with online help for the currently selected control or to the online support forums.
Search
Enter search criteria in the edit space provided and click the Search link to navigate directly to search on the Telerik web site.
110
Menu Designer
Adding Main Menu Items
There are multiple methods for building menus using the property collection editor or the RadMenu designer. To add a new main menu item, click the the RadMenu area labeled "Type here", and type your top level menu item directly into the entry space provided. When you're finished click ESC to abandon your edits or Enter to accept the edits and create a new RadMenuItem.
...Or click the drop-down arrow to the right of the existing main menu items and select one of the "Add" choices" to create an item of the corresponding type. Once the menu item is created you can use the Smart Tag to configure the Text, Image properties and edit the Items collection for the menu item.
111
...Or, click the RadMenu control, open its Smart Tag menu and select Edit Items. Add new RadMenuItems using the RadElement Collection Editor.
Each RadMenuItem can have its own items to allow menu designs that require multiple levels of hierarchy.
112
AngleTransform sets the angle offset from horizontal with which the item will be displayed. CommandBinding allows you to configure keyboard shortcuts to fire a given menu item. See the Getting Started topic for an example. DisplayStyle lets you choose whether to show an image, text, or both on the item. DescriptionText contains the text for the description that appears just below the Text. DescriptionFont controls the font characteristics of the DescriptionText display. Enabled when set to false shows the menu item as grayed out and does not react to mouse clicks. To allow non-standard painting when the menu item is not enabled set the UseDefaultDisabledPaint property to false and then use the Visual Style Builder to customize the appearance of this state. FlipText flips the text of the item vertically if set to True. BackColor and ForeColor set the colors of the background and text. Font sets the font and size of the item text. HintText is the text that can appear on the right side of the menu item, such as "Ctrl+N" for "New". Image, ImageIndex, and ImageKey let you assign an image to display on the item. To use ImageIndex and ImageKey you will need to assign the RadMenu ImageList property to an ImageList in the component tray. CheckOnClick indicates whether selecting the item should set a check mark. IsChecked controls whether a check mark is displayed on the item. TextImageRelation controls the relationship between the text and image displayed on the item. Text specifies the text to show on the item. TextOrientation allows you to choose vertical or horizontal text display. PopupDirection indicates whether the direction in which the drop-down menu will open will be to the left, right, up, or down. ShowArrow displays an arrow button on the drop-down menu when there are sub-menus as shown on the "Open" menu item below.
113
[VB] Altering the Arrow and Popup Direction miOpen.Layout.ArrowPrimitive.Direction = Telerik.WinControls.ArrowDirection.Down miOpen.Layout.ArrowPrimitive.ForeColor = Color.Red miOpen.PopupDirection = Telerik.WinControls.UI.RadDirection.Down [C#] Altering the Arrow and Popup Direction miOpen.Layout.ArrowPrimitive.Direction = Telerik.WinControls.ArrowDirection.Down; miOpen.Layout.ArrowPrimitive.ForeColor = Color.Red; miOpen.PopupDirection = Telerik.WinControls.UI.RadDirection.Down;
StringAlignment formats the alignment of the text string so it is positioned near, center, or far from the left border of the menu item.
RadMenuComboItem
The RadMenuComboItem allows you to put a combo box on a menu. To add items to the combo box work with the Items collection of the RadMenuComboItem.ComboBoxElement property. Because the ComboBoxElement returns a RadComboBox, you can also use data binding to put items in the combo box from any data source.
RadMenuSeparatorItem
The RadMenuSeparatorItem is used to add a horizontal line for visual separation between successive items on a menu.
RadMenuButtonItem
This menu item has button appearance and behavior. It also does not have HintText, DescriptionText and does not have an IsChecked property. The screenshot below shows a RadMenuButtonItem with text "Start Server".
RadMenuHeaderItem
This menu itemdisplays header text as shown in the screenshot below with text "Network Tasks".
114
[VB] Adding Menu Items Public Sub New() InitializeComponent() radMenu1.Items.Add(New RadMenuItem("Item 1")) radMenu1.Items.Add(New RadMenuItem("Item 2")) radMenu1.Items.Add(New RadMenuItem("Item 3")) Dim item1 As RadMenuItem = DirectCast(radMenu1.Items(0), RadMenuItem) item1.Items.Add(New RadMenuItem("Sub menu item 1")) item1.Items.Add(New RadMenuItem("Sub menu item 2")) (DirectCast(item1.Items(0), RadMenuItem)).Click += New EventHandler(Form1_Click) End Sub Sub Form1_Click(sender As Object, e As EventArgs) RadMessageBox.Show("You clicked " + (TryCast(sender, RadMenuItem)).Text) End Sub [C#] Adding Menu Items public Form1() { InitializeComponent(); radMenu1.Items.Add(new RadMenuItem("Item 1")); radMenu1.Items.Add(new RadMenuItem("Item 2"));
115
Only certain element types can be nested at design-time, i.e.RadMenuItem, RadMenuButtonItem, RadMenuHeaderItem, RadMenuSeparatorItem and RadComboItem. All other elements can be nested by wrapping the in RadMenuItemBase. Follows an example of creating check box menu item: [VB] Creating check box menu item Public Class CustomCheckMenuItem Inherits RadMenuItemBase Private checkBoxElement As RadCheckBoxElement Protected Overrides Sub CreateChildElements() MyBase.CreateChildElements() checkBoxElement = New RadCheckBoxElement() checkBoxElement.Padding = New Padding(20, 0, 0, 0) checkBoxElement.CheckMarkPrimitive.Margin = New Padding(0, 0, 5, 0) Me.Children.Add(checkBoxElement) End Sub Public Overrides Property Text() As String Get Return checkBoxElement.Text End Get Set(ByVal value As String) checkBoxElement.Text = value End Set End Property Public Custom Event ToggleStateChanged As StateChangedEventHandler
116
117
[C#] Adding the custom item to the Items collection public Form1() { InitializeComponent(); CustomCheckMenuItem checkBoxItem = new CustomCheckMenuItem(); checkBoxItem.Text = "Check Box"; checkBoxItem.ToggleStateChanged += new StateChangedEventHandler (checkBoxItem_ToggleStateChanged); radMenuItem1.Items.Add(checkBoxItem); } void checkBoxItem_ToggleStateChanged(object sender, StateChangedEventArgs args) { RadMessageBox.Show("Check box state has changed to " + args.ToggleState); } You can find the complete source for this project at: \Menu\<VB or CS>\MenuAddCheckBoxItem
Finding Items
RadMenu Items can be located by name through accessing the item through the indexer. The example below gets the top level "File" menu, then indexes the next level of Items to get the "Open" menu item, then removes the "Open" menu item. [VB] Locating Items Using Indexer Dim fileItem As RadMenuItem = DirectCast(radMenu1.Items("miFile"), RadMenuItem) Dim openItem As RadMenuItem = DirectCast(fileItem.Items("miOpen"), RadMenuItem) If openItem <> Nothing Then fileItem.Items.Remove(openItem) End If [C#] Locating Items Using Indexer RadMenuItem fileItem = (RadMenuItem)radMenu1.Items["miFile"]; RadMenuItem openItem = (RadMenuItem)fileItem.Items["miOpen"]; if (openItem != null) { fileItem.Items.Remove(openItem); } RadMenu Items collection also enables using LINQ clauses for finding menu items based on RadItem properties, such as the Text property. See the articles in MSDN (Microsoft Developer's Network) Language Integrated Query (http://msdn.microsoft.com/en-us/library/bb397926.aspx)pagefor more information about LINQ. Here is an example that shows finding menu items based on the Text property of the item, changing the tool tip
118
[VB] Finding and Removing Menu Items Private Sub btnGo_Click(sender As Object, e As EventArgs) Dim fileItem As RadMenuItem = DirectCast(radMenu1.Items("miFile"), RadMenuItem) Dim openItem As RadMenuItem = DirectCast(fileItem.Items("miOpen"), RadMenuItem) If openItem <> Nothing Then fileItem.Items.Remove(openItem) End If ' finds the "Save" item from the "File" Items collection Dim saveItem As RadMenuItem = DirectCast(fileItem.Items.FirstOrDefault(Function(item As ) item.Name.Equals("miSave")), RadMenuItem) If saveItem <> Nothing Then saveItem.ToolTipText = "Next automatic save at " + DateTime.Now.AddHours(0.5) End If End Sub [C#] Finding and Removing Menu Items private void btnGo_Click(object sender, EventArgs e) { RadMenuItem fileItem = (RadMenuItem)radMenu1.Items["miFile"]; RadMenuItem openItem = (RadMenuItem)fileItem.Items["miOpen"]; if (openItem != null) { fileItem.Items.Remove(openItem); } // finds the "Save" item from the "File" Items collection RadMenuItem saveItem =
119
Background Images
You can place a background image underneath your menu. It can even be an irregular image as shown in the in example demos that ship with the product.
In the example below a RadPanel has the BackGroundImage property assigned and the RadMenu sits within the middle of the panel space. To make the image show through, hide the fill primitive of the menu and the "File" menu item.
[VB] Setting a Transparent Background radMenu1.MenuElement.Children(1).Visibility = ElementVisibility.Hidden radMenu1.Items(0).Children(0).Visibility = ElementVisibility.Hidden [C#] Setting a Transparent Background radMenu1.MenuElement.Children[1].Visibility = ElementVisibility.Hidden; radMenu1.Items[0].Children[0].Visibility = ElementVisibility.Hidden;
Context Menus
With context menus you can pop up a context-specific set of choices anywhere in the user interface, either attaching the menu to a control or programmatically in any location on the form that suits you. Context menus can be attached to RadControls and any other System.Windows.Forms.Control descendant for that matter.
120
Using RadContextMenu
To get started with context menus, drop a RadContextMenu on the form. This is a non-visual component that will be placed below the form in the component tray.
Add menu entries by adding to the Items collection at design time or programmatically. Although there is no Menu Designer, the Smart Tag "Edit Menu Items" will still bring up the RadItem Collection Editor where you can add/edit/delete items just as you can with RadMenu.
121
Using RadContextMenuManager
Standard Winforms visual controls all have a ContextMenuStrip property that is not used by RadContextMenu. Instead, each control that you want to associate a context menu with needs to have a RadContextMenu property. To get this property to appear, drop a RadContextMenuManager component onto thecomponent tray to automatically associate a RadContextMenu property with every control on the form.RadContextMenuManager is a non-visual component and has no significant properties.The sole purpose of RadContextMenuManager is to populate controls on the form with the RadContextMenu property.
122
123
124
Name = "miGiftType1", Text = "Birthday". Name = "miGiftType2", Text = "Anniversary". Name = "miGiftType3", Text = "Thank You". Name = "miGiftType4, Text = "Get Well Soon".
3. Select Edit Menu Items from the Smart Tag of "cmDeliveryMethod". Add four RadMenuButtonItems with the following properties:
Name = "mbiDeliveryMethod1", Text = "Priority Overnight". Name = "mbiDeliveryMethod2", Text = "Standard Overnight". Name = "mbiDeliveryMethod3", Text = "2 Day". Name = "mbiDeliveryMethod4, Text = "3 Day".
4. In the Solution Explorer, navigate to the Properties folder, Resources.resx item. Double-click Resources.resx to open the resources editor. 5. Drag an assortment of jpg or png images from the file explorer into the resources editor.
6. On the form's surface drop the following controls and set properties. The layout should look something like the screenshot below:
125
RadLabel: Text = "Gift Type", ThemeName = Office2007Silver. RadTextBox: Name = "tbGiftType", NullText = "Right-click to enter a gift type", ThemeName = Office2007Silver. RadLabel: Text = "Wrapping", ThemeName = Office2007Silver. RadPanel: Name = "pnlWrappingPaper", Text = "Right-click to choose wrapping paper", ThemeName = Office2007Silver. Label: Name = "lblDeliveryMethod", Text = "Right-click to chooses delivery method"
7. Double click the form to create a form load event handler. Add the code below to disable the "gift type" Microsoft context menu, hook up a new mouse down event handler and call helper method LoadWrappingContextMenu(). The mouse down event handler and LoadWrappingContextMenu() will be written later. [VB] Handling the Form Load Event Private Sub RadForm1_Load(sender As Object, e As EventArgs) tbGiftType.TextBoxElement.TextBoxItem.HostedControl.ContextMenuStrip = New ContextMenuStrip () tbGiftType.TextBoxElement.MouseDown += New MouseEventHandler(TextBoxElement_MouseDown) LoadWrappingContextMenu() End Sub [C#] Handling the Form Load Event private void RadForm1_Load(object sender, EventArgs e) { tbGiftType.TextBoxElement.TextBoxItem.HostedControl.ContextMenuStrip = new ContextMenuStrip(); tbGiftType.TextBoxElement.MouseDown += new MouseEventHandler(TextBoxElement_MouseDown); LoadWrappingContextMenu(); } 8. Make sure you have the following references in your "Imports" (VB) or "uses" (C#) section of your code: [VB] Adding Namespace References
126
127
128
13. In the Properties window, events tab, locate "miGiftType1" and set the Click event to "miGiftTypeClick". Repeat this step for "miGiftType2", "miGiftType3" and "miGiftType4". 14. Press Ctl-F5 to run the application. Right-click each of the prompts to see the context menus.
129
RadApplicationMenu is the Telerik counterpart of the "application menu" that displays controls used to perform actions on entire documents and forms, such as Save and Print. It also provides a list of recent documents, access to form options, and the ability to exit the form or application.
RadApplicationMenu
RadApplicationMenu is essentially a RadDropDownButton and has many of the same properties and design time interfaceasa RadMenu, i.e. same Smart Tag items, RadItem Collection Editor and the same RadItem types that may be added to the collection. In the case of RadApplicationMenu, there are three RadItem collections: Items, RightColumnItems, and ButtonItems. The RightColumnWidth property allows you to reserve extra screen real estate. RadApplicationMenu also has a DisplayStyle property that may be Image (default), None, Text and ImageAndText.Set the Image property to include yourlogo or whatever icon you want to use. The screenshot belowshows all three collections populated and the Image set to a "world globe" icon.
130
RadRibbonBar
RadRibbonBar Structure
The ribbon bar has a complex structure, but can be broken down into these main pieces. The screenshot below should help you visually place where the pieces go.
Start menu: The Start Menu is a RadApplicationMenu described earlier in this chapter. Quick Access Tool Bar: This contains a few often used items that can be any of the button types shown in the screenshot below or a separator item. Use the QuickAccessToolBarItems collection to populate the tool barand toggle QuickAccessToolbarBelowRibbon onif the tool bar should appear below the tabbed area.
131
Tabs: The tabs are the first level of organization in the main part of RadRibbonBar. Tabs are typically used to split the functionality of an application into major areas. Each tab is a member of the ribbon bar's CommandTabs collection. You can create tabs by clicking the Add New Tab... prompt in the designer:
...or clicking the Add Tab Smart Tag command or editing the ribbon bar's CommandTabs collection:
132
Groups: Each tab hosts one or more groups. A groups is a container for other containers and individual functional elements. Groups can individually collapse if there is not enough room to display them all. You can add groups by clicking the Add New Group... prompt in the designer:
Each CommandTab contains an object representing a tab, but also contains an Items collection that contain RadRibbonBarGroup objects. So you can also add groups by using thetab's collection editor:
133
Button Groups: Groups may contain one or more button groups. A button group is a container of nested button groups or individual functional elements. Button group Orientationcan be Horizontal (containing a horizontal row of elements) or Veritical (containing a vertical column of elements). You can add button groups from the group Smart Tag...
134
135
Elements: Elements are individual functional pieces of the RadRibbonBar. Elements can be contained directly within groups or within button groups. Groups and button groups can contain a variety of elements. You can add elements using the context menuor Items collection of either a group or button group.
136
Contextual Tabs
Contextual tabs (also called tab groups) provide a way to organize related tabs. They are often used to group tabs that apply to a specific object in your application.
In the screenshot above, "Selection" and "Table Tools" are contextual tabs. Their width indicates the tabs that they contain, so that the Selection contextual tab includes the Selected Text tab, and the Table Tools contextual tab includes the Layout and Design tabs. Color is also used to unify a contextual tab with its contained group's. The tabs that belong to contextual tabs are always placed to the right of other tabs on the Telerik RadRibbonBar. You can create new context tab groups using the Add New Group... prompt in the designer, or editing the ContextualTabGroups property of the ribbon bar control. To add a tab to the group, drag the tab to the group and drop it there.
Galleries
A gallery is a special type of element that is designed to allow the user to select visually from among a number of choices. A gallery may be displayed in either collapsed or expanded view. In its default collapsed view, a gallery shows a single row of choices, as well as up and down arrows for scrolling to other rows of choices and a drop-down arrow for switching to expanded view.
In its expanded view, a gallery shows all of its choices at one time, a filter selection bar at the top, and tools at the bottom.
137
To create a gallery, right-click a group on a RadRibbonBar control in design view. Select Add an Item, and then RadGalleryElement. To add items to the gallery, select the RadGalleryElement control and edit the Items collection. You can set the text and an image for each RadGalleryItem in the collection. Adding Groups Groups organize the items within a gallery into distinct sections. In the screenshot of the expanded gallery above, Plain Tables and Built-In are groups. To add a group: 1. Select the RadGalleryElement control. 2. Click in the Groups property, and then click the ellipsis button. 3. In the RadItem Collection Editor, click Add to add a new group. 4. Set the Text property to the caption of the new group. 5. Click in the Items property of the RadGalleryGroupItem, and then click the ellipsis button. 6. Click Add to add an item to the group. Each time you click Add, one of the items that you already created will be added to the group.
138
7. Click OK when you are done adjusting item membership in the group. 8. Click OK when you are done creating groups. Creating Filters Filters let you select which groups to display. For example, the All Tables filter in the screenshot above includes the Plain Tables group and the Built-In group. 1. Select the RadGalleryElement control. 2. Click in the Filters property, and then click the ellipsis button. 3. In the RadItem Collection Editor, click Add to add a new filter. 4. Set the Text property to the caption of the new filter. 5. Click in the Items property of the RadGalleryGroupFilter, and then click the ellipsis button. 6. Click Add to add a group to the filter. Each time you click Add, one of the groups that you already created will be added to the filter. 7. Click OK when you are done adjusting group membership in the filter. 8. Click OK when you are done creating filters. Creating Tools You can add tools to be displayed beneath the gallery when it is in an expanded mode. Select the RadGalleryElement and edit the Tools collection.
139
Name = "miNew", Text = "New", ImageKey = <key of the "New" image> Name = "miOpen", Text = "Open", ImageKey = <key of the "Open" image> Name = "miSave", Text = "Save", ImageKey = <key of the "Save" image>
140
2. Open the RadRibbonBar QuickAccessToolBarItems property and add the following RadButtonElements:
Name = "qaOpen", DisplayStyle = Image, ImageKey = <key of the "Open" image> Name = "qaSave", DisplayStyle = Image, ImageKey = <key of the "Save" image> Name = "qaHelp", DisplayStyle = Image, ImageKey = <key of the "Help" image>
141
3. Click the Add New Tab... prompt in the designer and enter "Home" for the tab text.
4. Click the Add New Group... prompt. Select the newgroup and set the Text property to "Clipboard".
Name = "miCut", Text = "Cut", ImageIndex = <index of the "Cut" image> Name = "miCopy", Text = "Copy", ImageIndex = <index of the "Copy" image>
142
Name = "cbBold", Text = "Bold", DisplayStyle = "Image", ImageIndex = <index of the "Bold" image> Name = "cbItalic", Text = "Italic", DisplayStyle = "Image", ImageIndex = <index of the "Italic" image>
7. In the Properties window for the RadRibbonBar, locate the OptionsButton property and expand the item. Set the Visibility property to "Collapsed". Note: there are two buttons on the bottom right of the start menu, "Options" and "Exit". We will hide the Options and implement the exit to replace our "Quit" menu item. 8. In the Properties window Events tab, locate the ExitButton property and expand the item. Double-click the Click event to create an event handler. Move your "this.Close()" code to this handler. 9. In the Properties window Events tab, hook up the remaining menu item Click or ToggleStateChanged event handlers for each element.
6.8 Summary
In this chapter you learned how to add drop-down and context menus to your application using RadMenu, RadContextMenu and RadContextMenuManager controls. We began with a tour of usability and feature highlights, then learned how to build menus at design-time using the Menu Designer. You learned common menu item collection programmatic tasks such as adding and removing menu items,locating and modifying menu items. You learned how to programmatically pop up a context menu in a specific screen location.Finally, the chapter introduces the RadRibbonBar andRadApplicationMenu controls and explored their use.
143
7.1 Objectives
Learn some of the basic capabilities, architecture and class hierarchy of the Telerik Presentation Foundation. Become familiar with the classes used directly in the controls, i.e. RadElement and RadControl. See how elements are accessed within RadControls. See how elements can be added to RadControls. Learn how to add any Control descendant using a RadHostItem as a wrapper.
7.2 Introduction
The Telerik Presentation Foundation (TPF) offers Windows Presentation Foundation (WPF) features within classic Windows Forms applications. TPFis the foundation for all RadControls for Winforms controls and objects.
All controls have access to common services provided by TPF such as theming, animation, layout and property binding. No matter how complex a control may be, a control is built up from a few simple types of elements. By working with these elements, you can customize any control on a very granular level. The uniform nature of the control architecture makes it possible to nest controls within each other for more flexible and modern user interfaces. All elements in a control element tree inherit common property values from their parent elements unless these values are set locally. This feature helps each element use less memory while still providing finegrained customization options.
Control Architecture
Controls in the RadControls for WinForms suite have both a general shared architecture and a specific internal structure.
144
A number of pre-built primitives are available for building themable user interfaces quickly including text, gradient fills, borders, checks, arrows, lines, radio buttons, images and trackbars. Elements combine primitives to form the basis of a functioning control. For example, RadLabelElement combines a BorderPrimitive, FillPrimitive and TextPrimitive, then adds specific label properties TextAlignment and BorderVisible. Layout elements descending from LayoutPanel manage the arrangement of child elements. For example, StackLayoutPanel arranges elements in a horizontal or vertical stack that may wrap to new lines. StripLayoutPanel orders elements in a single vertical or horizontal line. RadControls are typically thin wrappers around a component element, handle any direct communication with Windows and establish communication to the RadElement by creating a root element and adding elements to the root element. RadLabel for example simply creates a root element and then creates and adds a RadLabelElement to the root element.
145
3. This brings up the Element Hierarchy Editor dialog. Notice the Control element structure on the left side of the dialog. The top level element is called RootRadElement and contains a RadButtonElement. The constituent parts of the RadButtonElement are the FillPrimitive, alayout panel to arrange image and text, BorderPrimitive and FocusPrimitive. Select the "RadButtonElement" node of the element tree and change properties: TextImageRelation = TextBeforeImage, Text = "World Clock", Padding = "10, 10, 10, 10". When setting the Text property, use the drop down arrow button to open RadMarkUpEditor, where you can make different modifications.Enter "World", hit enter, enter "Clock", then choose Font "Segoe Script" and make the text Bold. Click Apply to confirm the changes.
146
4. Select the "FillPrimitive" node and and set properties: BackColor = "Blue", BackColor2 = "LightBlue", BackColor3 = "Lavender", BackColor4 = "Purple", GradientStyle = "OfficeGlass". 5. Select the "ImagePrimitive" node and set properties: Image = <the image of a globe, or any small image (around 32 x 32 pixels)>, Opacity = "0.5". 6. Select the "BorderPrimitive" node and set the Visibility property to Collapsed in order to hide the border around the button 7. Click the Close button to view the button.
147
Properties in primitives are often surfaced to higher level objects in the element tree. Using the Hierarchy editor makes it possible to get at properties that haven't been surfaced yet. The point of this exercise was to use some of the lower level primitives and make the button look much different than the default version. In a more typical development situation, look for the highest level where the property appears.
RadProperty encapsulates properties used in RadObject. Each RadProperty has a name, type, owner and
148
RadPropertyMetadata describes a property and de-couples the information about a property from the property itself. RadObject represents the base class for all RadElement objects and has the ability to store all property values in a single structure. RadElement is a key class that represents the smallest unit in a RadControl that can be painted or laid out on the screen. RadElement is the base class of all elements that take advantage of TPF features, e.g. property inheritance, layouts and styling. RadElement implements a tree-like structure of RadObjects, property value inheritance and automatic layout and display invalidation based on the options of the PropertyMetadata for each RadProperty. RadElement has a size and location specified in coordinates in relation to its parent. VisualElement adds visual properties common to all elements that will be painted, e.g. back color, fore color, font, default size, smoothing mode, opacity. LayoutPanel is an abstract class descending from RadElement. LayoutPanel descendants coordinate sizing and position for a number of elements. RadComponentElement implements IComponent and introduces the ability to be contained. BasePrimitive is a VisualElement descendant that adds a virtual PaintPrimitive() method that draws a primitive to the screen. RadItem represents a visual element which could be added to an ItemsCollection and can be selected, deleted or moved at design time. By default this class knows how to handle user input. RadControl is the abstract base class for all RadControls. Each RadControl contains a tree of RadElements. The tree has a root, the RadControl.RootElement (type RootRadElement shown in the diagram) and children of the root element. RadControl acts as a bridge between traditional Windows forms controls and the RadElement tree. RadControl also defines properties common across all controls e.g. ThemeName, Style, ImageList, image scaling properties, minimum and maximum sizes.
7.5 Primitives
Primitives are the elements in the control element tree that are painted to the screen when Windows displays a form containing a Telerik RadControl. All primitives are derived from BasePrimitive, a subclass of VisualElement. BasePrimitive adds the virtual PaintPrimitive() method to VisualElement. The descendants of BasePrimitive override this virtual function to draw themselves. Individual primitive classes expose additional properties. For example, the TextPrimitive class includes a Text property, which specifies the text that it will place on the screen. Browse through these available primitive types to see what you can include in your own RadControl customizations: Primitive Example Description The ArrowPrimitive draws a filled triangular polygon. Orientation is controlled by the Direction property with possible ArrowDirection enumeration values of Up, Down, Left or Right. The arrow is filled with the ForeColor property value. This example draws a border primitive and an ArrowPrimitive.
ArrowPrimitive
149
BorderPrimitive
CheckPrimitive
FillPrimitive
150
GripPrimitive
GripPrimitive displays a vertical row of dots as a visual cue to users that this is an area that can be gripped and dragged. GripPrimitive is used in the RadToolStrip to display on the left hand side of each strip. Grip dots are displayed using BackColor and BackColor2 colors. BackColor2 represents a shadow to set the dots off the background, particularly when the dots and the background contain some of the same colors.
ImagePrimitive
Use the ImagePrimitive class whenever you need to draw an image as part of rendering a control. The properties specific to displaying images are Image, ImageKey, ImageIndex and ImageScaling. Note: the ImageList property is introduced in the RadControl class.
151
LinePrimitive
OverflowPrimitive
ProgressBarPrimitive
152
RadioPrimitive
RectanglePrimitive
TextPrimitive
TrackBarPrimitive
153
FocusPrimitive
7.6 Elements
Elements fall into three categories, depending on their base class:
Layout elements derive from LayoutPanel. Each LayoutPanel arranges child items in a particular manner. Painted elements derive from BasePrimitive. They override the OnPaint method to draw figures on the controls graphic surface. Component elements derive from RadItem. RadItem descendants handle user input and can be worked with in the design environment. A component element overrides the virtual CreateChildElements() method to create one or more layout elements and primitives. Typically TPF based controls are simple wrappers around RadItem descendant classes, and the RadItem descendant classes define logic and user interface.
The code below will match the second button to look like the first.
154
As you will see, the trick is to traverse the Children RadElementCollection, locate the correct element and cast it to the appropriate type. The example below first gets the RadButtonElement and uses that to access the other elements. This top level element is often surfaced as a property, e.g. you can reference "radButton1.ButtonElement" instead of "radButton1.RootElement.Children". [VB] Setting Button Element Properties Public Sub New() InitializeComponent() ' get the "ButtonElement", just under the root element, ' set the padding and text Dim buttonElement As RadButtonElement = TryCast(radButton2.RootElement.Children(0), RadButtonElement) buttonElement.TextImageRelation = TextImageRelation.TextBeforeImage buttonElement.Padding = New Padding(10) buttonElement.Text = "World" + Environment.NewLine + "Clock" ' access the fill primitive, use "OfficeGlass" style and set coloring Dim fillPrimitive As FillPrimitive = DirectCast(buttonElement.GetChildrenByType(GetType (FillPrimitive))(0), FillPrimitive) fillPrimitive.GradientStyle = Telerik.WinControls.GradientStyles.OfficeGlass fillPrimitive.BackColor = Color.Blue fillPrimitive.BackColor2 = Color.LightBlue fillPrimitive.BackColor3 = Color.Lavender fillPrimitive.BackColor4 = Color.Purple ' get the image primitive and set image. Set the opacity to be 50% transparent. Dim imagePrimitive As ImagePrimitive = TryCast(DirectCast(buttonElement.Children (1).Children(0), ImagePrimitive), ImagePrimitive) imagePrimitive.Image = Properties.Resources.Globe imagePrimitive.Opacity = 0.5 ' get the text primitive and set the font to use a bold, script Dim textPrimitive As TextPrimitive = TryCast(DirectCast(buttonElement.Children(1).Children (1), TextPrimitive), TextPrimitive) textPrimitive.Font = New Font("Segoe Script", 8.25F, FontStyle.Bold) ' get the border primitive and hide it.
155
156
You can find the complete source for this project at: \TPF\<VB>|CS>\AddingElements [VB] Composing Elements Private Sub Form1_Load(sender As Object, e As EventArgs) ' Create a stack panel to contain the title and bullet points
157
158
Create an instance of the control. Create a RadHostItem and pass the control instance in the constructor. Add the RadHostItem to the Children collection of your control or item.
Let's say we have aRadListControl and want to add to its items a GroupBox.For this scenario, in the CreatingVisualListItem event of RadListControl, we are going to createa GroupBox and RadHostItem and pass the GroupBox in the constructor of RadHostItem. Then add the RadHostItem to the Children collection of an instance of RadListVisualItem and assign the newly created visual item to the visual item from theevent arguments. You can find the complete source for this project at: \TPF\<VB|CS>AddingControlsToElements [VB] Adding and Configuring RadHostItems Private Sub RadForm1_Load(ByVal Handles MyBase.Load RadListControl1.Items.Add("Item RadListControl1.Items.Add("Item RadListControl1.Items.Add("Item End Sub sender As System.Object, ByVal e As System.EventArgs) 1") 2") 3")
Private Sub RadListControl1_CreatingVisualListItem(ByVal sender As Object, ByVal args As Telerik.WinControls.UI.CreatingVisualListItemEventArgs) Handles RadListControl1.CreatingVisualListItem 'make the items autosize
159
160
Animation
You can animate aspects of RadElements based on a property change. The animation can be another property that is smoothly transitioned between states. The screenshot below shows the "FishEyeBar" project underway. When the mouse moves over an element, the element is scaled up to a larger size. As the mouse moves off the item, the item smoothly scales back down to its original size.
161
You can find the complete source for this project at: \TPF\<VB|CS>\FishEyeBar Examine the code for the FishEyeBar project. Most of the code we're interested in occurs in the WelcomeScreenBottom.cs user control. The starting point is to define a descendant of PropertyChangedBehavior. Notice that the constructor base() takes a reference to a RadProperty. This is the property that will trigger the behavior. Try changing this to a IsMouseDown property and the behavior will not happen on mouse over but only when you click the mouse button. [VB] Inheriting from PropertyChangeBehavior Public Class WelcomeScreenMouseOverBehavior Inherits PropertyChangeBehavior Public Sub New() MyBase.New(RadItem.IsMouseOverProperty) End Sub '... End Class [C#] Inheriting from PropertyChangeBehavior public class WelcomeScreenMouseOverBehavior : PropertyChangeBehavior { public WelcomeScreenMouseOverBehavior() : base(RadItem.IsMouseOverProperty) { } //... } Another critical piece for implementing the PropertyChangeBehavior is to override the OnPropertyChange method. In this method you define what animations will take place. This is done by creating an AnimatedPropertySetting and applying that setting to the element you want to animate. The AnimatedPropertySetting constructor lets you define the property to be animated and several overloads include:
Properties for controlling the smoothness and speed of the animation, i.e. number of frames, step and interval between frames. Start and end property values.
In this example the ScaleTransformProperty is used to scale the element to a larger size. [VB]Appling animation
162
163
7.8 Summary
In this chapter you learned some of the capabilities, architecture and class hierarchy of the Telerik Presentation Foundation. We paid special attention to the classes used directly in the controls, i.e. RadElement and RadControl.We took a brief look at the structure, WPF resemblance and how the elements interact. We saw how the elements could be accessed within RadControls and could be combined to create new unique controls. You also learned how to add any Control descendant using RadHostItem as a wrapper.
164
PageView
8.1 Objectives
Tour the usability and feature highlights of RadPageView. Explore the tabbed interface and manage controls within associated content panels. Perform common Items collection programmatic tasks such as adding, removing, iterating, locating and selecting pages. Handle page layout and dimensions. Handle conditions where the number of pages overflow the available space. Work with page images, text and custom controls. Page drag and drop
8.2 Introduction
A tabbed interface can supply intuitive navigation between application areas. RadPageView supplies the basis for building tabbed interfaces with rich formatting and behavior. Page items can have any shape you can imagine, be rearranged with drag-and-drop, edited, and automatically manage other controls on associated content panels. Some RadPageView highlights:
Assign any shape to individual page items. The shape can be one of a predefined list or you can create a custom shape in the Shape Designer tool and assign it to the page item.
Use themes to customize the appearance of RadPageView, including changing appearance on selection or mouse over.
165
- Strip Mode
166
- Stack Mode
- Outlook Mode
167
- ExplorerBar Mode
168
Get fine grain control over the layout of the page. Display text in horizontal or vertical orientation, or at any angle. Anchor page items on any side of the control.
169
Display images and text on page items. You can control the layout of the picture relationship to the text.
170
Allow page scrolling and overflow management if there are more pages than can be displayed at one time.
171
You can also add different controls to the pages, arrange them just like in a form or panel.
172
173
Search Disconnected Drive You can typically find images in the Visual Studio "Common7\VS2008ImageLibrary\1033" directory in "VS2008ImageLibrary.zip".
The images for the screenshots used in this example were found in the zipped image library under "VS2008ImageLibrary\Objects\png_format\WinVista" directory.
Size = 630, 350 MinimumSize = 630, 350 Text = "Drive Info" ThemeName = "Desert"
4. Drop a RadPanel and a RadPageView on the form and arrange them to roughly the same proportions as the example below.
RadPanel: Text = "", ThemeName = "Desert", Anchor = "Top, Left, Right". RadPageView:ThemeName ="Desert",Anchor = "Top, Bottom, Left, Right".
174
RadLabel: Text = "Drive Name:" RadLabel: Name = "lblDriveName", Text = "x". RadLabel: Text = "Drive Format". RadLabel: Name = "lblDriveFormat", Text = "x". RadLabel: Text = "Total Space:". RadLabel: Name = "lblTotalSpace", Text = "x". RadLabel: Text = "Volume Label:". RadLabel: Name = "lblVolumeLabel", Text = "x". RadLabel: Text = "Drive Type:". RadLabel: Name = "lblDriveType", Text = "x". RadButton: Name = "btnSearch", Text = "Find Max Free Space", ThemeName = "Desert", Anchor = "Top, Right", ImageList = "ilDriveTypes", ImageKey = <the key for the "search" image>". RadToggleButton: Name = "btnShow", Text = "Show Disconnected Drives", ThemeName = "Desert", Anchor = "Top, Right", ImageList = "ilDriveTypes", ImageKey = <the key for the "disconnected drive" image>, IsChecked = True.
175
6. Add two more pages from the Smart Tag(to get a total of three)
176
7. Set their names - the first page to "C:\", the second to "D:\" and the last one to "E:\".
177
178
8. Assign the appropriate images from the ImageList to the pages of RadPageView in code: [VB] Set the images toRadPageView pages RadPageViewPage1.Image = ilDriveTypes.Images("Hard_Drive.png") RadPageViewPage2.Image = ilDriveTypes.Images("CD_ROM.png") RadPageViewPage3.Image = ilDriveTypes.Images("Network.png") [C#] Set the images toRadPageView pages radPageViewPage1.Image = ilDriveTypes.Images["Hard_Drive.png"]; radPageViewPage2.Image = ilDriveTypes.Images["CD_ROM.png"]; radPageViewPage3.Image = ilDriveTypes.Images["Network.png"]; 9. Click the "C:\" pageand drop a RadListControl into the content area, just below the page button itself. Set the Name property of the list box to "lbFiles", Dock = "Fill", ThemeName = "Desert". For more detail about RadListControl, please see the upcoming ListControl chapter.
179
Common Tasks
From the Smart Tag Tasks menu you can select New Theme Manager to add a Theme Manager component to the
180
ViewMode lets you change the mode in which RadPageView will be displayed - Strip, Stack, Outlook or ExplorerBar mode ItemSize Mode determines whether the items should have equal size. The supported modes are EqualHeight, EqualWidth, EqualSize and Individual. Item Drag Mode determines the drag mode of the items. The supported modes are Preview and Immediate. Item Content Orientation determines the orientation of the item content (image, text, and buttons' panel). The supported orientations are Auto, Horizontal, Horizontal180, Vertical90 and Vertical270. Item Spacing determines the spacing between the items in pixels.
StripView tasks:
Strip Alignment determines the position of the tab items in RadPageView in relation to the content area. It can be Top, Left, Bottom or Right. Item Alignment determines the alignment of items within the strip layout. Item Fit Mode determines the fit mode of the items. The available modes are None, Fill, Shrink and ShrinkAndFill. Strip Buttons determines the style of the navigation buttons. The available styles are None, Auto, LeftScroll, RightScroll, Scroll, VS2005Style, Close, ItemList, VS2008Style, All.
181
Pages
Add Pageallows you to add new page to RadPageView Remove Page - removes the last added page.
182
You can also add controls to RadPageView content area programmatically: [VB] Adding Controls to RadPageViewPage Dim page1 As New RadPageViewPage() page1.Text = "Page 1" radPageView1.Pages.Add(page1) Dim button As New RadButton() button.Text = "I am a button" button.Size = New System.Drawing.Size(100, 20) page1.Controls.Add(button) [C#] Adding Controls to RadPageViewPage RadPageViewPage page1 = new RadPageViewPage(); page1.Text = "Page 1";
183
Gotcha! You can also access RadPageViewPage byindex or the Text of the page into the page view Pages collection, [VB] Accessing Items Collection radPageView1.Items(0).ContentPanel.Controls.Add(button) radPageView1.Items("Page 1").ContentPanel.Controls.Add(button) [C#] Accessing Items Collection radPageView1.Items[0].ContentPanel.Controls.Add(button); radPageView1.Items["Page 1"].ContentPanel.Controls.Add(button);
All. When this option is selected. RadPageView will display all the available strip buttons - left scroll button, right scroll button, overflow button and close button:
184
185
ItemList. Displays a drop-down button that invokes a drop-down list of the items:
VS2008Style. Displays the item list drop-down button and the close button:
186
Layout
By default, when you drop RadPageView on the Form, the StripAlignment property is set to Top, and its member tabs are inserted with their TextOrientation property set to Horizontal. These default settings cause the tabs to appear above the RadPageView's baseline, and the text is oriented parallel to the baseline:
The RadPageView StripAlignment property can be set to Top, Bottom, Left, or Right: [VB] Set the strip alignment Dim element As RadPageViewStripElement = DirectCast(Me.radPageView1.ViewElement, RadPageViewStripElement) element.StripAlignment = StripViewAlignment.Left [C#] Set the strip alignment RadPageViewStripElement element = (this.radPageView1.ViewElement as RadPageViewStripElement); element.StripAlignment = StripViewAlignment.Left;
187
TextOrientation can be Vertical or Horizontal to the current baseline.The example below has tabs positioned to the left and TextOrientation is Vertical (i.e. perpendicular to the baseline): [VB] Set the strip alignment Dim element As RadPageViewStripElement = DirectCast(Me.radPageView1.ViewElement, RadPageViewStripElement) element.TextOrientation = Orientation.Vertical; [C#] Set the strip alignment RadPageViewStripElement element = (this.radPageView1.ViewElement as RadPageViewStripElement); element.TextOrientation = Orientation.Vertical
EqualHeght - makes the height for all tabs the same, even when images or multiple lines of text make the content of some tabs larger. Otherwise, each tab height is automatically sized to fit the content.
188
Multiple Tab Lines You can get multiple lines of text in a tab by either appending Environment.NewLine programmatically to the Text property string.
EqualWidth respectively makes the width of all tabs the same EqualSize makes both width and height for all tabs the same Individual this mode autosizes all tabs according to their content (text or image) individually
ItemSpacing set the spacing between the different tabs. The following image demonstrates this property set to 15 pixels.
ItemFitMode By default, tab width is sized to according to its content - ItemFitMode is None:
When the ItemFitMode property is set to Fill, tab width takes up all the available horizontal space. As more tabs are added, they shrink (up to the moment when the tabs content can be visible) to accomodate new arrivals. The screenshot below shows page view with ItemFitMode set to Fill and four initial tabs. After pressing a button that adds new tabs programmatically, the tabs shrink to fit all tabs until there is enough room for them without disturbing the content of the tabs.
189
In the case where ItemFitMode is set to Shrink the items are shrinking when there is not enough room for them, without considering the tab content:
The last option is ShrinkAndGrow and as its name speaks it combines the Fill and the Shrink modes - the tabs are filling the entire space (when such exists) and they shrink when there is no enough room to fit them.
[VB] Setting Text and Font radPageViewPage2.Text = "Dynamic Tab" radPageViewPage2.Item.Font = New System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Italic) [C#] Setting Text and Font radPageViewPage2.Text = "Dynamic tab"; radPageViewPage2.Item.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Italic);
190
[VB] Adding Multiple Lines Programmatically radPageViewPage1.Text = "First line" + Environment.NewLine & "Second line" [C#] Adding Multiple Lines Programmatically radPageViewPage1.Text = "First line" + Environment.NewLine + "Second line";
Text Orientation
You can set the text orientation for each tab individually by assigning TextOrientation to Vertical or Horizontal (the default). To grab fine grained control you canuse the AngleTransform property instead.
[VB] Setting the TextOrientation radPageViewPage1.Item.TextOrientation = Orientation.Vertical radPageViewPage2.Item.AngleTransform = 45 radPageViewPage3.Item.AngleTransform = 120 radPageViewPage4.Item.AngleTransform = 220 radPageViewPage5.Item.AngleTransform = -35 [C#] Setting the TextOrientation radPageViewPage1.Item.TextOrientation = Orientation.Vertical; radPageViewPage2.Item.AngleTransform = 45; radPageViewPage3.Item.AngleTransform = 120; radPageViewPage4.Item.AngleTransform = 220; radPageViewPage5.Item.AngleTransform = -35;
Images
You can display images for each page item. Assign the Image property of the desiredpage either from the ImageList, loading from disk or assigning an image resource. Strip view:
191
ExplorerBar mode:
Outlook mode:
192
[VB] Methods to Assign Tab Images radPageViewPage1.Image = Image.FromFile("C:\image.png") radPageViewPage2.Image = Resources.disk radPageViewPage3.Image = imageList1.Images("help.png") [C#] Methods to Assign Tab Images radPageViewPage1.Image = Image.FromFile(@"C:\image.png"); radPageViewPage2.Image = Resources.disk; radPageViewPage3.Image = imageList1.Images["help.png"];
193
Visibility
By default, the page item Visibility property is set to Visible. This setting means that the tab and its ContentPanel can be seen and manipulated by the end user at run time.
You can also set the Visibility property to Hidden where neither the tab nor its ContentPanel are visible, but a space is left open in the RadPageView at run time for the hidden tab.
If you set the page item's Visibility property to Collapsed, the tab and its associated ContentPanel are invisible, and the space occupied by the tab is removed.
194
You can find the complete source for this project at: \Tabs\<VB|CS>\FindItem The project requires references to Telerik.WinControls, Telerik.WinControls.UI and Telerik.WinControls.Enumerations in the "Imports" (VB) or "uses" (C#) section of code. [VB] Iterating the Items Collection Private Sub radCheckBox1_ToggleStateChanged(ByVal sender As Object, ByVal args As StateChangedEventArgs) Handles RadCheckBox1.ToggleStateChanged For Each page As RadPageViewPage In RadPageView1.Pages If (page.Tag.ToString().Equals("advanced") And args.ToggleState.Equals(ToggleState.On)) Then page.Item.Visibility = ElementVisibility.Collapsed Else page.Item.Visibility = ElementVisibility.Visible End If Next page End Sub [C#] Iterating the Items Collection private void radCheckBox1_ToggleStateChanged(object sender, StateChangedEventArgs args) { foreach (RadPageViewPage page in radPageView1.Pages) { bool isAdvanced = page.Tag.ToString().Equals("advanced"); page.Item.Visibility = isAdvanced & args.ToggleState == ToggleState.On ? ElementVisibility.Collapsed : ElementVisibility.Visible; } }
Finding Items
The RadPageView Pages collection has a series of extension methods that implement functions for finding and performing other operations on page items. Include a reference to System.Linq so that these extension methods will show up. Here is an example that duplicates the effect of the previous "Iterating items" example. The code uses the Where() method to select all page items with a Tag property of "advanced". The returned IEnumerable collection is iterated and the visibility is set to Collapsed if the checkbox is selected.
195
Extending theRadPageViewItem (in this case RadPageViewStripItem) withRadProgressBarElements in it. Adding pages dynamically. Adding controls dynamically to the pages. Iterating pages. Associating images with page items. Layout and position of text, images and custom elements.
Use the Environment.GetLogicalDrives() method to retrieve a list of drive name strings (e.g. "C:\", "D:\", etc.), then create a DriveInfo object, passing the drive name in the constructor. The DriveInfo object provides the data displayed in the panel at the top of the form, the type of drive used to index into the images used to represent each drive and the amount of total and free space used to format progress bars displayed in each page item. The System.IO Directory.GetDirectories() method returns an array of directories that are listed in the page below each page item.
196
Telerik.WinControls Telerik.WinControls.Enumerations The project should already have System.IO and Telerik.WinControls.UI references from the "Getting Started" project.
Populate RadPageView
1. In the form constructor after the InitializeComponent call, add a call to LoadTabStrip(). LoadTabStrip() is a private method we will write in upcoming steps that populates the page view with pages for each drive on the local machine and content panels listing the directories for each drive. [VB] Calling LoadTabStrip Public Sub New() InitializeComponent() LoadPageView() End Sub [C#] Calling LoadTabStrip public RadForm1() {
197
Creates a new RadPageViewPage that stores the associated DriveInfo object in the Tag property. Creates a new RadListControl and populates it with the directories. Calculates the amount of used drive space. [VB] Adding Helper Methods #Region "helper methods" ' Create and configure a single RadPageViewPage and populate the ' tag with the DriveInfo passed Private Function GetDrivePageItem(ByVal driveInfo As DriveInfo) As RadPageViewPage Dim page As New RadPageViewPage() page.TextImageRelation = TextImageRelation.ImageBeforeText page.TextAlignment = ContentAlignment.TopCenter page.ImageAlignment = ContentAlignment.TopLeft page.Tag = driveInfo Return page End Function ' Create, configure and populate a RadListControl with files from the ' drive root. Private Function GetListControl(ByVal drive As String) As RadListControl Dim listControl As New RadListControl() listControl.Dock = DockStyle.Fill listControl.ThemeName = "Desert" Dim directories As String() = Directory.GetDirectories(drive.ToString()) For Each directory As String In directories listControl.Items.Add(New RadListDataItem(directory)) Next Return listControl End Function ' Get the percent of used space on a drive Private Function GetUsedPercent(ByVal driveInfo As DriveInfo) As Integer Return CInt(Math.Truncate((CDbl(driveInfo.TotalSize) - CDbl(driveInfo.AvailableFreeSpace)) / CDbl(driveInfo.TotalSize) * 100)) End Function #End Region [C#] Adding Helper Methods #region helper methods // Create and configure a single RadPageViewPage and populate the // tag with the DriveInfo passed private RadPageViewPage GetDrivePageItem(DriveInfo driveInfo) { RadPageViewPage page = new RadPageViewPage(); page.TextImageRelation = TextImageRelation.ImageBeforeText; page.TextAlignment = ContentAlignment.TopCenter; page.ImageAlignment = ContentAlignment.TopLeft; page.Tag = driveInfo; return page; }
198
199
200
201
Press Ctrl-F5 to run the application. You may first want to map a network drive or any USB drives you have available so that you have more drives to test against. Try running the application with your DVD or CD in
202
5. Double-click the "Find Max Free Space" button and add the following code to the Click event handler. The code iterates the pages comparing the DriveInfo drive space data looking for the greatest available free space. After the iteration, the pagepresenting the drive with the greatest free space is selected. [VB] Handing the "Find Max Free Space" Button Click Event Private Sub btnSearch_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnSearch.Click Dim selectedPage As RadPageViewPage = Nothing For Each page As RadPageViewPage In radPageView1.Pages ' no drive info, skip If page.Tag Is Nothing Then Continue For End If ' save first available tab with drive info If selectedPage Is Nothing Then selectedPage = page End If ' drive isn't ready, skip If Not TryCast(page.Tag, DriveInfo).IsReady Then Continue For End If ' save tab with greatest free space selectedPage = If(TryCast(selectedPage.Tag, DriveInfo).TotalFreeSpace > TryCast(page.Tag, DriveInfo).TotalFreeSpace, selectedPage, page) Next ' select tab with greatest free space radPageView1.SelectedPage = selectedPage End Sub [C#] Handing the "Find Max Free Space" Button Click Event private void btnSearch_Click(object sender, EventArgs e) {
203
204
205
PageViewItemDragMode.None - which is the default setting - disables the dragging functionality PageViewItemDragMode.Immediate - which applies the dragging operation without preview PageViewItemDragMode.Preview - which displays a preview of the dragging operation.
[VB] Setting Preview drag mode to RadPageView Dim element as New RadPageViewStripElement = DirectCast(Me.radPageView1.ViewElement, RadPageViewStripElement) element.ItemDragMode = PageViewItemDragMode.Preview [C#] Setting Preview drag mode to RadPageView RadPageViewStripElement element = (this.radPageView1.ViewElement as RadPageViewStripElement); element.ItemDragMode = PageViewItemDragMode.Preview;
206
[VB] Setting Preview drag mode to RadPageView Dim element as New RadPageViewStackElement = DirectCast(Me.radPageView1.ViewElement, RadPageViewStackElement) element.ItemDragMode = PageViewItemDragMode.Preview [C#] Setting Preview drag mode to RadPageView RadPageViewStackElement element = (this.radPageView1.ViewElement as RadPageViewStackElement); element.ItemDragMode = PageViewItemDragMode.Preview;
[VB] Setting Preview drag mode to RadPageView Dim element as New RadPageViewOutlookElement = DirectCast(Me.radPageView1.ViewElement, RadPageViewOutlookElement) element.ItemDragMode = PageViewItemDragMode.Preview [C#] Setting Preview drag mode to RadPageView RadPageViewOutlookElement element = (this.radPageView1.ViewElement as RadPageViewOutlookElement); element.ItemDragMode = PageViewItemDragMode.Preview;
207
[VB] Setting Preview drag mode to RadPageView Dim element as New RadPageViewExplorerBarElement = DirectCast(Me.radPageView1.ViewElement, RadPageViewExplorerBarElement) element.ItemDragMode = PageViewItemDragMode.Preview [C#] Setting Preview drag mode to RadPageView RadPageViewExplorerBarElement element = (this.radPageView1.ViewElement as RadPageViewExplorerBarElement); element.ItemDragMode = PageViewItemDragMode.Preview;
8.8 Summary
208
209
ListControl
9.1 Objectives
Learn how RadListControl and RadDropDownList are used to display data in list form for user selection. Learn common programmatic tasks: adding and removing items, iterating, locating and modifying items. Learn how to embed controls within items. Learn how to handle item layout, dimensions, images and text. Learn how to move items between list controls and drag and drop multiple items between list controls.
9.2 Introduction
RadListControl and RadDropDownList are enhanced, themablealternatives to the corresponding standard Windows Forms controls. Both controls are based on the Telerik Presentation Foundation and have a great deal of flexibility in what content can be included in theirs lists and how the content is arranged.
You can associate images and text descriptions with individual items in the drop-down list. Item and description fonts can be configured separately. The relationship of the text and image is configurable so that image or text can be on top or to the left. Images can have transparency and can be of any size.
Item text and image can be customized at design-time and run-time. Customization can be triggered based on the content of database data. Different image and text alignments are possible.
RadDropDownList provides flexible auto-completion options that suggest and append text from choices in the list as the user types.
210
Lists can be automatically sorted in ascending or descending order. At any time the list can be restored to the original order.
Form Design
1. Create a new Windows Forms application. 2. Add the following controls to the form and set properties. Arrange the controls to look something like the screenshot below.
RadButton: Name = "btnBack", Text = "Back" RadDropDownList: Name = "ddlDrives",Anchor = Top, Left, Right RadListControl: Name = "lcFiles", Anchor = Top, Bottom, Left, Right RadLabel: Name = "lblStatus", AutoSize = False, Dock = "Bottom", Size.Height = "20"
211
Adding Code
1. Add references to "Telerik.WinControls.UI" and "System.IO" to the "Imports" (VB) or "using" (C#) section of code. 2. Double-click the form to create a Load event handler. Add the code below. The event handler iterates the DriveInfo array returned by the static System.IO GetDrives()method. So that we don't leave the dropdown list text as "radDropDownList1", the SelectedIndex is set to the first entry in the list. In the next step we will include the AddDirectoryToDropDownList() method. [VB] Iterating DriveInfo Array Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load ' load the dropdown list with drive names and select the first one For Each driveInfo__1 As DriveInfo In DriveInfo.GetDrives() If driveInfo__1.IsReady Then Dim info As New DirectoryInfo(driveInfo__1.RootDirectory.FullName) AddDirectoryToDropDownList(info, ddlDrives) End If Next ddlDrives.SelectedIndex = 0 End Sub [C#] Iterating DriveInfo Array private void Form1_Load(object sender, EventArgs e) { // load the dropdown list with drive names and select the first one foreach (DriveInfo driveInfo in DriveInfo.GetDrives()) {
212
213
214
The key item here is the "Edit Items" link used to display the RadListDataItem Editor dialog where you can add such items to the Items collection of both controls.
215
216
If you want to add items at a specific location within the list, use the Insert() method and pass the index where the item should be included. [VB] Inserting to the Collection radListControl1.Items.Insert(0, New RadListDataItem("put me at the top of the list")) [C#] Inserting to the Collection radListControl1.Items.Insert(0, new RadListDataItem("put me at the top of the list")); If you have the data for all the items you want to add up front, you can include them at one once using the AddRange() method. [VB] Using AddRange() radListControl1.Items.AddRange(New RadListDataItem() {New RadListDataItem("One"), New RadListDataItem("Two"), New RadListDataItem("Three")}) [C#] Using AddRange() radListControl1.Items.AddRange(new RadListDataItem[] {
217
[VB] Adding and Arranging Images Dim item As New RadListDataItem("Telerik") item.Image = Image.FromFile("C:\Program Files (x86)\Telerik\RadControls for WinForms Q1 2011 \Examples\QuickStart\Resources\telerikLOGO.png") item.TextImageRelation = TextImageRelation.ImageAboveText item.TextAlignment = ContentAlignment.BottomCenter radListControl1.Items.Add(item) Dim item1 As New RadListDataItem("RadControls for WinForms") item1.TextAlignment = ContentAlignment.MiddleLeft radListControl1.Items.Add(item1) Dim item2 As New RadListDataItem("Q1 2011") item2.TextAlignment = ContentAlignment.MiddleRight radListControl1.Items.Add(item2) radListControl1.AutoSizeItems = True [C#] Adding and Arranging Images RadListDataItem item = new RadListDataItem("Telerik"); item.Image = Image.FromFile(@"C:\Program Files (x86)\Telerik\RadControls for WinForms Q1 2011\Examples\QuickStart\Resources\telerikLOGO.png"); item.TextImageRelation = TextImageRelation.ImageAboveText; item.TextAlignment = ContentAlignment.BottomCenter; radListControl1.Items.Add(item); RadListDataItem item1 = new RadListDataItem("RadControls for WinForms"); item1.TextAlignment = ContentAlignment.MiddleLeft; radListControl1.Items.Add(item1); RadListDataItem item2 = new RadListDataItem("Q1 2011"); item2.TextAlignment = ContentAlignment.MiddleRight; radListControl1.Items.Add(item2); radListControl1.AutoSizeItems = true; By substituting RadDropDownList for RadListControl and adding to aRadListDataItems collection, you can reuseall the code above. Here are the results in a RadDropDownList.
218
Locating Items
You can use the FindString method to get the index of an item with specified text. If the index eqals "-1",this means that no items with the specified text isfound. For example, the code below finds the "Courier New" font family in the Items collection, scrolls to the item and selects it. [VB] Locating, Scrolling to and Selecting an Item Private Sub btnLocate_Click(sender As Object, e As EventArgs) Dim index As Integer = radListControl1.FindString("Courier New") Dim item As RadListDataItem = radListControl1.Items(index) If item IsNot Nothing Then radListControl1.ListElement.ScrollToItem(item) radListControl1.SelectedItem = item End If End Sub [C#] Locating, Scrolling to and Selecting an Item private void btnLocate_Click(object sender, EventArgs e) { int index = radListControl1.FindString("Courier New"); RadListDataItem item = radListControl1.Items[index]; if (item != null) { radListControl1.ListElement.ScrollToItem(item); radListControl1.SelectedItem = item; } }
219
Removing Items
To remove an item use the item collection Remove() method and pass a RadListDataItem that should be removed. If you know the ordinal position of the item, call RemoveAt()and pass the index. Toremove all items at once, call theClear() method.
Sorting
Both RadListControl and RadDropDownList have SortStyle properties that can be None, Ascending or Descending. The sort is performed against the Text property. [VB] Setting the Sort Private Sub Sort_ToggleStateChanged(sender As Object, args As StateChangedEventArgs) If sender = rbNone Then radListControl1.SortStyle = Telerik.WinControls.Enumerations.SortStyle.None ElseIf sender = rbAscending Then radListControl1.SortStyle = Telerik.WinControls.Enumerations.SortStyle.Ascending ElseIf sender = rbDescending Then radListControl1.SortStyle = Telerik.WinControls.Enumerations.SortStyle.Descending End If End Sub [C#] Setting the Sort private void Sort_ToggleStateChanged(object sender, StateChangedEventArgs args) { if (sender == rbNone) radListControl1.SortStyle = Telerik.WinControls.Enumerations.SortStyle.None; else if (sender == rbAscending) radListControl1.SortStyle = Telerik.WinControls.Enumerations.SortStyle.Ascending; else if (sender == rbDescending)
220
RadListControls
Selecting Items
The SelectionMode property determines if items in the list can be selected, if multiple items can be selected and the selection behavior when selecting multiple items.
A value of None prevents items from being selected. A value of One allows one item at a time to be selected. Selecting an item removes previous selections. MultiSimple allows the user to hold down the control or shift key and select multiple items, one at a time. MultiExtended allows the user to hold down the control key to select multiple items or to hold down the shift key and select multiple items in a range.
Run the sample project and select from the dropdown list to experiment with the selection behavior.
221
You can find the complete source for this project at: \ListControl\<VB|CS>\Programming To retrieve multiple selected items, iterate the RadListControl SelectedItems collection. [VB] Iterating the SelectedItems Collection Private Sub btnShowSelected_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnShowSelected.Click Dim builder As New StringBuilder() For Each item As RadListDataItem In RadListControl1.SelectedItems builder.Append(item.Text) builder.Append(Environment.NewLine) Next RadMessageBox.SetThemeName(Me.ThemeName) RadMessageBox.Show(builder.ToString(), "Your Selections") End Sub [C#] Iterating the SelectedItems Collection private void btnShowSelected_Click(object sender, EventArgs e) { StringBuilder builder = new StringBuilder(); foreach (RadListDataItem item in radListControl1.SelectedItems) { builder.Append(item.Text); builder.Append(Environment.NewLine); } RadMessageBox.SetThemeName(this.ThemeName); RadMessageBox.Show(builder.ToString(), "Your Selections"); }
222
223
Set the AllowDrop property of the target control to true. Define a MouseDown event handler for the source control where you call the DoDragDrop() method. You can pass an object in this method that identifies what is being dragged and specify what kind of drag operation you want to perform (move, copy, etc). Define a DragEnter event handler for the target control where you determine if the drag drop will be permitted. Arguments to this event handler provide the object being dragged and the drag operation being
224
Define a DragDrop event handler for the target control that performs the actual work suggested by the type of drag drop operation requested (i.e. move, copy, etc). Here we can reuse the MoveItems() method created in the previous exercise.
This works well when a single object is being dragged at a time, but with list controls we may want to select multiple items and drag them. To make this work, add these steps:
On MouseDown, Don't call DoDragDrop(). Instead, create a rectangle with the mouse position at its center. Store this rectangle in a private variable for use within other event handlers. Typically this rectangle is about 4 pixels wide and is defined by SystemInformation.DragSize. On MouseMove, check to see if the mouse has moved outside the rectangle, and if so, call DoDragDrop() here. On MouseUp, clear the variable holding the rectangle.
Thats enough to allow your user to select multiple items in a list control and drag them to another list control. Gotcha! There's a small usability issue that crops up. Item selection only occurs after MouseUp. So if you click an item and directly begin to drag, the selection hasn't happened yet and the drag operation doesn't see the item. So if you have two items already selected and click a third and drag, the first two are dropped but the last item gets missed. To work around this you need to detect the RadListDataItem under the mouse on MouseDown but before MouseUp. Save a reference to this item and add it to the SelectedItems collection before calling MoveItems(). That way you can keep your MoveItems() logic undisturbed and all the items will be dragged and dropped. 1. Set the RadListControl SelectionMode and AllowDrop properties either at design time or in code. Note: you don't need to set SelectionMode to make drag and drop work, but we want to show multiple files being dragged. [VB] Set RadListControls Properties Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load lcLeft.SelectionMode = SelectionMode.MultiExtended lcLeft.AllowDrop = True lcRight.SelectionMode = SelectionMode.MultiExtended lcRight.AllowDrop = True End Sub [C#] Set RadListControls Properties private void Form1_Load(object sender, EventArgs e) { lcLeft.SelectionMode = SelectionMode.MultiExtended; lcLeft.AllowDrop = true; lcRight.SelectionMode = SelectionMode.MultiExtended; lcRight.AllowDrop = true; } 2. Add a private variable to hold the "drag rectangle" that defines the zone the mouse must travel outside of before the drag begins. Also add a variable to hold the RadListDataItem that is directly under the mouse on MouseDown. [VB] Variables for the Drag Rectangle and Current RadListDataItem Private _dragRectangle As Rectangle = Rectangle.Empty Private _currentItem As RadListDataItem
225
Get a reference to the source RadListControl. Use the RadListControl ElementTree GetElementAtPoint() method to extract the RadListDataItem that is directly under the mouse and save it in "_currentItem". Create a Rectangle around the current mouse cursor position. Do this my creating a point above and to the left of the mouse cursor, where the distance is half the size of your rectangle dimensions. The rectangle dimensions are supplied by the SystemInformation.DragSize (typically 4 pixels in both dimensions). [VB] Handling the MouseDown Event Private Sub lcLeft_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs) Handles lcLeft.MouseDown ' get the listcontrol that items are being dragged from Dim sourceListControl As RadListControl = TryCast(sender, RadListControl) ' get the list control item directly under the mouse Dim element As RadElement = sourceListControl.ElementTree.GetElementAtPoint(e.Location) Dim visualItem As RadListVisualItem = TryCast(element, RadListVisualItem) If visualItem IsNot Nothing Then _currentItem = visualItem.Data ' create a "drag rectangle" with mouse in center Dim dragPoint As New Point(e.X - (SystemInformation.DragSize.Width / 2), e.Y (SystemInformation.DragSize.Height / 2)) _dragRectangle = New Rectangle(dragPoint, SystemInformation.DragSize) End If End Sub [C#] Handling the MouseDown Event private void lcLeft_MouseDown(object sender, MouseEventArgs e) { // get the listcontrol that items are being dragged from RadListControl sourceListControl = sender as RadListControl; // get the list control item directly under the mouse RadElement element = sourceListControl.ElementTree.GetElementAtPoint(e.Location); RadListVisualItem visualItem = element as RadListVisualItem; if (visualItem != null) { _currentItem = visualItem.Data; // create a "drag rectangle" with mouse in center Point dragPoint = new Point( e.X - (SystemInformation.DragSize.Width / 2), e.Y - (SystemInformation.DragSize.Height / 2)); _dragRectangle = new Rectangle(dragPoint, SystemInformation.DragSize); } }
4. Handle the MouseMove event. First check that we have at least one item to drop, thendetermine if the mouse has moved outside the "drag rectangle" by using the Rectangle Contains() method. If the mouse has moved outside, thencall the source RadListControl DoDragDrop() method. Pass a reference to the source RadListControl itself and aDragDropEffects flag that indicatesthat this is a Move operation.
226
227
228
RadDropDownList
RadDropDownList is essentially a RadListControl in a dropdown. It shares many of the behaviors of RadListControl, but has some additionalaspects particular tothe dropping down of the list and the text entry.
None to disallow resizing entirely. UpDownAndRightBottom to allow both horizontal and vertical resizing. UpDown to allow only vertical resizing. RightBottom to allow only horizontal resizing.
Editing
DropDownStyle determines if the text area at the top of the control can be edited. A setting of DropDown (the default) allows editing and the DropDownList setting shows the text area as read-only.
229
AutoComplete
RadDropDownList can automatically "suggest", or navigate to the closest match in the list as the user types and can append the closest choice to the entry in the textbox portion of the dropdown list. AutoCompleteMode controls this behavior:
None: Nothing happens when a user begins to type into the text box portion of the control. If the user types the whole text of an item and presses Enter, the item is selected.
Suggest: As the user types an entry into the text box, the drop-down portion of the control is shown and the items are filtered by the input text.
Append: As the user types, the next item in the list that matches the user input is automatically appended to the characters the user has already typed. The drop-down list is not shown without the user clicking the arrow.
SuggestAppend: Similar to the Append setting, but the drop-down list is shown and the filtered items according the input are shown.
Selecting Items
Unlike RadListControls, RadDropDownList has a single item selected at any time. Set the SelectedIndex to an ordinal value or set the SelectedItem property to a RadListDataItem instance. [VB] Setting the Selected item
230
Walkthrough
In this guided walk-through we will enhance the original "Getting Started" project to fine-tune and add features:
231
Display applications icons using the Windows Shell API Display a small icon in the edit portion of the dropdown list Open files in response to double-clicking the file list Display custom tool tips for each file item
Start with the "GettingStarted" project or a copy. In the designer, add a standard ImageList component. Using the Smart Tag Choose Images link, add an image to represent "Error". In this application the image key will be "Symbol Error.ico".
In the designer, select the "ddDrives" RadDropDownList and in the Properties window Events tab, remove the SelectedIndexChanged event. Later we will connect this event programmatically. In the Solution Explorer, add a new class file "Shell32.cs". Add the code below. This class is a wrapper for the Shell32.dll that contains Windows Shell API functions, including a function to retrieve abitmap from any file that contains an icon for itself. For more information, consult the online MSDN for articles on the Shell API and the System.Runtime.InteropServices namespace. [VB] Defining the Shell32 API Wrapper Class Imports System.Runtime.InteropServices ' Declares types and methods that can be called from the DLL Public Class Shell32 Public Shared Function GetFileBitmap(ByVal fileName As String) As Bitmap Dim result As Bitmap = Nothing Dim shFileInfo As New SHFILEINFO() Dim returnCode As IntPtr = SHGetFileInfo(fileName, 0, shFileInfo, Marshal.SizeOf (shFileInfo), SHGFI_ICON) If shFileInfo.hIcon <> IntPtr.Zero Then Dim icon As System.Drawing.Icon = System.Drawing.Icon.FromHandle(shFileInfo.hIcon) result = icon.ToBitmap() DestroyIcon(shFileInfo.hIcon) icon.Dispose()
232
233
Make sure the following namespace references exist in the "Imports" (VB) or "uses" (C#) clause. These references will support the Windows Shell API methods and other features as they are added. [VB] Adding Namespace References Imports Imports Imports Imports Imports Imports Imports System System.Drawing System.IO System.Text System.Windows.Forms Telerik.WinControls.Primitives Telerik.WinControls.UI
[C#] Adding Namespace References using System; using System.Drawing; using System.IO;
234
Add helper methods to work with FileSystemInfo and DirectoryInfo objects. [VB] Directory Helper Methods Private Function IsRootDirectory(ByVal info As DirectoryInfo) As Boolean Return info.Root.FullName.Equals(info.FullName) End Function Private Function IsDirectory(ByVal info As FileSystemInfo) As Boolean Return (info.Attributes And FileAttributes.Directory) = FileAttributes.Directory End Function Private Function IsHidden(ByVal info As FileSystemInfo) As Boolean Return (info.Attributes And FileAttributes.Hidden) = FileAttributes.Hidden End Function Private Function GetParentDirectory(ByVal info As FileSystemInfo) As DirectoryInfo Return New DirectoryInfo(Path.GetDirectoryName(info.FullName)) End Function [C#] Directory Helper Methods private bool IsRootDirectory(DirectoryInfo info) { return info.Root.FullName.Equals(info.FullName); } private bool IsDirectory(FileSystemInfo info) { return (info.Attributes & FileAttributes.Directory) == FileAttributes.Directory; } private bool IsHidden(FileSystemInfo info) { return (info.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden; } private DirectoryInfo GetParentDirectory(FileSystemInfo info) { return new DirectoryInfo(Path.GetDirectoryName(info.FullName)); }
Add private members that will be used to reference an image element in the dropdown list text area and a reference to the list item under the mouse during the last MouseDown. [VB] Add Private Members ' reference to element for image in dropdown list text area Private _imagePrimitive As ImagePrimitive ' stores a reference to item under last mouse down Private _currentItem As RadListDataItem [C#] Add Private Members // reference to element for image in dropdown list text area private ImagePrimitive _imagePrimitive; // stores a reference to item under last mouse down private RadListDataItem _currentItem;
235
236
237
Add helper methods toload dropdown list and list control. AddDirectoryToDropDownList() already exists in the "GettingStarted" project, so replace it with the code below. Both methods AddDirectoryToDropDownList() and LoadFilesListControl() take a DirectoryInfo and a reference to the control (list control or dropdown list) to load. AddDirectoryToDropDownList() loads a single directory path and image for the directory. LoadFilesListControl() iterates the FileSystemInfo objects within a directory and appends a list item for each. Notice that the call to GetFileSystemDescription() traps UnauthorizedAccessException and disables the item. [VB] Adding DropDownList and ListControl Helper Methods ' Add path and DirectoryInfo object to RadDropDownList Private Sub AddDirectoryToDropDownList(ByVal info As DirectoryInfo, ByVal dropDownList As RadDropDownList) If dropDownList.FindStringExact(info.FullName) = -1 Then Dim item As New RadListDataItem(info.FullName, info) item.Text = info.FullName item.TextImageRelation = TextImageRelation.ImageBeforeText ' use Shell32 api to get appication bitmap item.Image = Shell32.GetFileBitmap(info.FullName) dropDownList.Items.Add(item) End If dropDownList.SelectedItem = dropDownList.Items(dropDownList.FindStringExact(info.FullName)) End Sub ' load a RadListControl with the files in a directory Private Sub LoadFilesListControl(ByVal directoryInfo As DirectoryInfo, ByVal listControl RadListControl) listControl.Items.Clear() For Each info As FileSystemInfo In directoryInfo.GetFileSystemInfos() If Not IsHidden(info) Then ' add Text and Value in constructor Dim item As New RadListDataItem(info.Name, info) item.TextImageRelation = TextImageRelation.ImageBeforeText ' use the Shell32 API to get bitmap for file item.Image = Shell32.GetFileBitmap(info.FullName) listControl.Items.Add(item) Try GetFileSystemDescription(DirectCast(item.Value, FileSystemInfo), DescriptionDetail.Full) ' if directory cannot be accessed, disable item and include error message Catch ex As UnauthorizedAccessException item.Enabled = False End Try End If Next If listControl.Items.Count > 0 Then listControl.SelectedIndex = 0 End If
238
Replace the form Load event with the code below. The code that adds directories to the dropdown list is identical to the "GettingStarted" project. The purpose of code that follows it is to add an icon just to the left of the item text area. Additionally we subscribe to the ToolTipNeeded event of the control, where we display either the file information or the exception message if UnauthorizedAccessException is thrown.
239
To display the image on the left side of the text use the element tree from the SmartTag >> Edit UI Element to locate the textbox element. This element is needed because we are going to add the image for the text area in the textbox element children collection.
[VB] Handling the Form Load and ToolTipTextNeededEvents Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load ' load the dropdown list with drive names and select the first one For Each driveInfo__1 As DriveInfo In DriveInfo.GetDrives() If driveInfo__1.IsReady Then Dim info As New DirectoryInfo(driveInfo__1.RootDirectory.FullName) AddDirectoryToDropDownList(info, ddlDrives) End If Next ' get references to the textbox element and the textbox item within the element Dim textBoxElement As RadTextBoxElement = ddlDrives.DropDownListElement.TextBox Dim textBoxItem As RadTextBoxItem = textBoxElement.TextBoxItem ' Add extra padding on the left for the new image textBoxItem.Margin = New Padding(20, 1, 1, 1) ' pad the element so textboxitem doesn't overwrite the ' border on the right side textBoxElement.Padding = New Padding(2, 2, 20, 2) ' save a reference _imagePrimitive = New ImagePrimitive() AddHandler lcFiles.ToolTipTextNeeded, AddressOf lcFiles_ToolTipTextNeeded AddHandler ddlDrives.SelectedIndexChanged, AddressOf ddlDrives_SelectedIndexChanged 'insert the ImagePrimitive to the text box element textBoxElement.Children.Insert(0, _imagePrimitive) 'hide the FillPrimitive so the image to be displayed textBoxElement.Fill.Visibility = Telerik.WinControls.ElementVisibility.Collapsed 'select the first item in the dropdown ddlDrives.SelectedIndex = 0
240
241
Replace the SelectedIndexChanged event with the code below. You'll see this pattern of code in several places where the cursor is set to the "WaitCursor", if there's an exception, the ShowStatus() method displays the exception message and finally the cursor is restored to its default. The code inside the Try{} block is much the same as the "GettingStarted" example except now the "Back" button is disabled if we're already at the root. Also, here's where you set the custom image for the RadDropDownList text area. [VB] Handling the SelectedIndexChanged Event Private Sub ddlDrives_SelectedIndexChanged(ByVal sender As Object, ByVal e As Telerik.WinControls.UI.Data.PositionChangedEventArgs) Cursor.Current = Cursors.WaitCursor Try Dim directoryInfo As DirectoryInfo = TryCast(ddlDrives.SelectedValue, DirectoryInfo) btnBack.Enabled = Not IsRootDirectory(directoryInfo) LoadFilesListControl(directoryInfo, lcFiles) Dim selectedImage As Image = TryCast(ddlDrives.SelectedItem, RadListDataItem).Image _imagePrimitive.Image = selectedImage.GetThumbnailImage(16, 16, Nothing, New IntPtr()) Catch ex As UnauthorizedAccessException ShowStatus(ex) Finally Cursor.Current = Cursors.[Default] End Try End Sub [C#] Handling the SelectedIndexChanged Event void ddlDrives_SelectedIndexChanged(object sender, Telerik.WinControls.UI.Data.PositionChangedEventArgs e) { Cursor.Current = Cursors.WaitCursor; try { DirectoryInfo directoryInfo = ddlDrives.SelectedValue as DirectoryInfo; btnBack.Enabled = !IsRootDirectory(directoryInfo); LoadFilesListControl(directoryInfo, lcFiles); Image selectedImage = (ddlDrives.SelectedItem as RadListDataItem).Image; _imagePrimitive.Image = selectedImage.GetThumbnailImage(16, 16, null, new IntPtr());
242
Press Ctrl-F5 to run the application so far. Icons should display next to all the drives in the drop down and in the list controlas well.The textbox portion of the RadDropDownList should have a thumbnail representation of the drive icon.
The tool tip should display timestamp statistics and the number of bytes/objects in each folder/file.
243
244
In the Properties window Events tab, hook up "lcFiles"with the new MouseDown, MouseUp and DoubleClick event handlers. Handle the "Back" button click event. The logic here gets the parent of the current directory and calls AddDirectoryToDropDownList. This has the effect of adding that directory to the dropdown list, making that directory the current item in the dropdown list and loading all the files for that directory into the "lcFiles" list control. [VB] Handling the Click Event Private Sub btnBack_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnBack.Click Cursor.Current = Cursors.WaitCursor Dim directoryInfo As DirectoryInfo = TryCast(ddlDrives.SelectedValue, DirectoryInfo) AddDirectoryToDropDownList(GetParentDirectory(directoryInfo), ddlDrives) Cursor.Current = Cursors.[Default] End Sub End Class [C#] Handling the Click Event private void btnBack_Click(object sender, EventArgs e) { Cursor.Current = Cursors.WaitCursor; DirectoryInfo directoryInfo = ddlDrives.SelectedValue as DirectoryInfo; AddDirectoryToDropDownList(GetParentDirectory(directoryInfo), ddlDrives); Cursor.Current = Cursors.Default; }
Press Ctrl-F5 to run the application again.You should be able to navigate around the directory structure. The "Back" button should be enabled only when you're not at the root level and should move you back one directory level. Double-clicking a folder should drill down into that folder, add it to the RadDropDownList and display all the objects in that directory. Again, be careful of what you click on. System.Diagnostics.Process.Start() will run whatever executable you double-click. This is also true of .bat files or any other executable. Just as with the Windows File Explorer, double-clicking files will run whatever program is associated with that file
245
9.6 Summary
In this chapter you explored how to work with RadListControl and RadDropDownList, to add and remove items from their collections, to customize the aitems appearance and to use the different functionalities that these controls offer. Also, you have learnt how to make a drop down functionality between list controls.
246
10.1 Objectives
Get familiar with theRadListView control. Learn how to add items, columns and groups at design-time and using code. Learn how to group, filter and sort data based on user input. Display data in different views. Customize the view appearance.
10.2 Introduction
Telerik RadListView control is created as a result of the concord of the powerful data layer used by RadGridView (Section 21.2) and RadListControl (Section 9.2) , together with the outstanding Telerik Presentation Framework (Section 7.2) . The data layer provides very high performance when working with data and also different types of binding options. Additionally, it provides features like grouping, sorting and filtering. Thanks to the Telerik Presentation Framework the control customization is very flexible and intuitive. RadListView is a bindable control for representing and editing list data with lots of customization abilities. First of all, RadListView will offer three different types of views, which will let you visualize your data the way that you want. You may choose between SimpleListView, IconView or DetailView. RadListView will also provide a rich and flexible API, which will let the developers easily customize the layout or the behavior of the control. Furthermore, the API will be similar to the API of our existing controls, so it will be easier for those who have already used our products to use the new component. The known family of items creating/formatting events will let you replace or style the items according to your preferences. Check boxes, resizing and reordering of columns, hot tracking, multiple selection and different sizing modes are another small part of the possibilities provided by the API. At design time, you will be able to easily choose a data source or populate it with unbound items, groups and columns. Last, but not least, RadListView will support kinetic scrolling mechanism which is a great advantage when used for applications deployed on Kiosks. Follows a list of the features that RadListView supports:
DataBinding ViewTypes ListView, DetailsView and IconsView Columns Sorting Grouping Filtering Kinetic scrolling CheckBoxes Multi selection Hot tracking
247
10.3 GettingStarted
This article, will show you how in a few clicks in design time you can setup your RadListView control.
248
249
7. From the Smart Tag, select the Add Items.. option and add a few items to the control.
250
9. Assign images to the respective items. The images are in the project resources.
10. Set the AllowArbitraryItemHeigh to true, in order to allow items to size themselves in heightaccording to
251
11. Add three RadButtons below the form with the following parameters:
Name: radButton1 = listViewButton; radButton2 = detailsViewButton; radButton3 = iconsViewButton Text: listViewButton.Text = "ListView"; detailsViewButton.Text = "DetailsView"; iconsViewButton.Text = "IconsView"
12. Subscribe for these buttons click events and set the respective ViewType of RadListView in each event handler. Additionally, set the AllowArbitratyItemHeight to true when changing to DetailsView or ListView and AllowArbitratyItemWidth to true for IconsView: [C#] Change ViewType of RadListView private void listViewButton_Click(object sender, EventArgs e) { radListView1.ViewType = ListViewType.ListView; radListView1.AllowArbitraryItemHeight = true; } private void detailsViewButton_Click(object sender, EventArgs e) { radListView1.ViewType = ListViewType.DetailsView; radListView1.AllowArbitraryItemHeight = true; } private void iconsViewButton_Click(object sender, EventArgs e) { radListView1.ViewType = ListViewType.IconsView; radListView1.AllowArbitraryItemWidth = true; }
[VB.NET] Change ViewType of RadListView Private Sub listViewButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles listViewButton.Click RadListView1.ViewType = ListViewType.ListView RadListView1.AllowArbitraryItemHeight = True End Sub
252
14. In order to setup the DetailsView, open the Smart Tag of RadListView in design time and select Add Columns..
253
15. Add two columns. Change the header text of the first one to "Name" and of the second one to "Description"
16. In order to assign the item values for a specific column in design time, you can use the SubItems property of RadListDataItem. Open the items collection, and click the SubItems property:
254
17. Assign some name and description in the StringCollectionEditor. First line adds value for the first column, second line for the second column etc.
18. Thats all. Run the application and review the three views offered by RadListView.
255
Add Items
Adding items to RadListView at design time is possible through the Items collection of the control. This collection is accessible by using the Smart Tag or the Items collection property in the property grid.
256
Both of these will open ListViewDataItemCollectionEditor, from where, by clicking the Add button you can add items to the collection. Additionally, on the right hand side,. you will see a property grid, where you can change the properties of each item individually.
257
Add Columns
When RadListView ViewType is set to DetailsView, the data can be displayed in columns view. Adding columns to the control at design time, is done by populating the Columns collection of RadListView. This collection can be accessed either through the Columns property in the property grid of the control or through the Smart Tag of RadListView.
258
Once ListViewDetailColumn collection editor is open, you can add as many columns as you need, and also, you can modify their properties in the property grid.
259
Once the Columns collection is populated, you can assign values for each column of each ListViewDataItem, by making use of the SubItems property (this property is available in design-time only):
260
Add Groups
Items in RadListView can be grouped conveniently into different groups, which will enhance your end-user experience when working with RadListView. Grouping the items at design time can be achieved by setting the EnableCustomGroups and ShowGroups properties of the control to true and, adding the desired groups into the Groups collection of RadListControl. This collection is accessible either through the Smart Tag of the control or through the Groups collection property located in the property grid.
261
Once the ListViewDataItemGroup collection is opened, you can add the desired groups by using the Add button on the bottom, and also, you can modify the group settings in the property grid.
262
After the desired groups are added, you can easily assign each ListViewDataItem to the group of your choice by setting the ListViewDataItem.Group property:
263
264
You can find the complete source for this project at: \ListView\<VB|CS>\Programming For the matter of this example we are going to use a DataTable containing data about Artists, Albums, Songs and Image.
1. First lets create a form with RadCommandBar (Section 14.2) docked Top and RadListView docked Fill. Add a Strip to RadCommandBar and populate it with the following items: CommandBarLabel
265
Name: commandBarDropDownSort Text: "" Items: None, Song Name, Artist, Album
CommandBarDropDownList
CommandBarSeparatorItem CommandBarLabel
Text: Group By: Name: commandBarDropDownGroup Text: "" Items: None, Album, Artist
CommandBarDropDownList
CommandBarSeparatorItem
Name: commandBarToggleList ToolTipText: ListView Image: Some image representing ListView Name: commandBarToggleTiles ToolTipText: IconsView Image: Some image representing IconsView Name: commandBarToggleDetails ToolTipText: DetailsView Image: Some image representing DetailsView
CommandBarToggleButton
CommandBarToggleButton
CommandBarToggleButton
CommandBarSeparatorItem CommandBarTextBox
266
3. Now let continue with setting the control DataSource, allow edit and remove operations and subscribe to the events that we are going to use in this example. [C#] Initial settings this.radListView1.ItemDataBound += new Telerik.WinControls.UI.ListViewItemEventHandler (radListView1_ItemDataBound); this.radListView1.VisualItemFormatting += new Telerik.WinControls.UI.ListViewVisualItemEventHandler(radListView1_VisualItemFormatting); this.radListView1.CellFormatting += new Telerik.WinControls.UI.ListViewCellFormattingEventHandler(radListView1_CellFormatting); this.radListView1.ColumnCreating += new ListViewColumnCreatingEventHandler (radListView1_ColumnCreating); this.radListView1.ViewTypeChanged += new EventHandler(radListView1_ViewTypeChanged); this.radListView1.AllowEdit = false; this.radListView1.AllowRemove = false; this.radListView1.DataSource = this.songsDataTableBindingSource; this.radListView1.DisplayMember = "SongName"; this.radListView1.ValueMember = "SongID"; this.radListView1.ViewType = ListViewType.IconsView; [VB.NET] Initial settings AddHandler Me.RadListView1.ItemDataBound, AddressOf radListView1_ItemDataBound AddHandler Me.RadListView1.VisualItemFormatting, AddressOf radListView1_VisualItemFormatting AddHandler Me.RadListView1.ViewTypeChanged, AddressOf radListView1_ViewTypeChanged
267
268
269
SetupDetailsView - here we will set the AllowArbitraryItemHeight, property to true, in order to allow the items to size themselves in height, according to their content.
270
SetupIconsView - here we will define a custom size for the items, set some spacing between the items and again set the AllowArbitraryItemHeight, property to true SetupSimpleListView - in this method we will only set the AllowArbitraryItemHeight, property to true.
In the ViewTypeChanged event handler, we will simply check which is the new view and call the corresponding setup method [C#] Handling view type changes private void SetupDetailsView() { this.radListView1.AllowArbitraryItemHeight = true; } private void SetupIconsView() { this.radListView1.ItemSize = new Size(200, 64); this.radListView1.ItemSpacing = 5; this.radListView1.AllowArbitraryItemHeight = true; } private void SetupSimpleListView() { this.radListView1.AllowArbitraryItemHeight = true; } void radListView1_ViewTypeChanged(object sender, EventArgs e) { switch (radListView1.ViewType) { case ListViewType.ListView: SetupSimpleListView(); break; case ListViewType.IconsView: SetupIconsView(); break; case ListViewType.DetailsView: SetupDetailsView(); break; } } [VB.NET] Handling view type changes Private Sub SetupDetailsView() Me.RadListView1.AllowArbitraryItemHeight = True End Sub Private Sub SetupIconsView() Me.RadListView1.ItemSize = New Size(200, 64) Me.RadListView1.ItemSpacing = 5 Me.RadListView1.AllowArbitraryItemHeight = True End Sub Private Sub SetupSimpleListView()
271
272
273
274
275
276
10.6 Summary
In this chapter you have learnt how to useRadListView in the different ViewType modes,somebasic customizations and working with the functionalities that the control provides - sorting, filtering and grouping.
277
278
11.1 Objectives
Learn how to start using RadPropertyGrid Learnhow to setup the control. Explore its functionalities. Find our its formatting capabilities. Learn how to use the Validation functionalities of RadPropertyGrid.
11.2 Introduction
RadPropertyGrid for WinForms displays the properties of a given object in a user-friendly way allowing the enduser to edit these properties using our editors. Now you can concentrate all the settings in one place instead of scattering them all over your forms. RadPropertyGrid gives the end-user the ability to filter, group and sort its items thanks to our data processing engine used also by controls like RadGridView, RadListView etc. RadPropertyGrid takes full advantage of the virtualization mechanism, so even if you load an object with hundreds of properties, no problem, RadPropertyGrid will handle these cases.
279
280
7. Now, let's create custom object with different type of public properties and one private property: [C#] Custom object public class Dog { public string Name { get; set; } public int Age { get; set; } public double Weight { get; set; } public string Gender{ get; set; } public bool Homeless { get; set; } public DateTime Birthday { get; set; } private string OwnerName { get; set; } } [VB.NET] Custom object Public Class Dog Public Property Name() As String Get Return m_Name End Get Set(ByVal value As String) m_Name = Value
281
282
283
284
From the Smart Tag of the control, you can enable the most commonly used functionalities in RadPropertyGrid - .Filtering, Sorting, Grouping - and also, you can show or hide the help bar and the tool bar.
285
11.5 Programming
In the following tutorial, you will get familiar with the control, its basic functionalities and its basic customization abilities. You can find the complete source for this project at: \PropertyGrid\<VB|CS>\GettingStarted 1. Create a new Windows Forms application. 2. In the Solution Explorer, delete the default form. 3. Also in the Solution Explorer, right-click the project and select Add | New Item... from the context menu. 4. Select the "Telerik RadForm" template and click the Add button to close the dialog. 5. After the form is created, increase its size in height and drag RadPropertyGrid control to it. 6. Now underneath the form, add four RadButtons with the following properties and create their click event handlers
Name: sortButton, Text: Add SortDescriptor Name: filterButton, Text: Add FilterDescriptor
286
Name: groupButton, Text: Add GroupDescriptor Name: clearButton, Text: Clear tDescriptor
8. Let's start with the code. First we are going to set theSelectedObject to PropertyGridElement: [C#] Set SelectedObject radPropertyGrid1.SelectedObject = new PropertyGridElement(); [VB.NET] Set SelectedObject RadPropertyGrid1.SelectedObject = New PropertyGridElement() 9. Next, lets show the built-in toolbar,which providesthe user with grouping,sorting and filteringout of the box: [C#] Show the toolbar radPropertyGrid1.ToolbarVisible = true; [VB.NET] Show the toolbar
287
[VB.NET] Add custom button to toolbar Dim clearFiltering As New RadButtonElement() clearFiltering.Text = "Clear" clearFiltering.MinSize = New System.Drawing.Size(25, 22) clearFiltering.StretchHorizontally = False RadPropertyGrid1.PropertyGridElement.ToolbarElement.Children.Add(clearFiltering) AddHandler clearFiltering.Click, AddressOf clearFiltering_Click [VB.NET] Clear filter text box Private Sub clearFiltering_Click(ByVal sender As Object, ByVal e As EventArgs) RadPropertyGrid1.PropertyGridElement.ToolbarElement.SearchTextBoxElement.Text = "" End Sub 11. Let's set the BedingEditMode property to BeginEditOnClick, in order to start the editing process on the first mouse click. Alternative options are BeginEditOnSecondClick or BeginEditProgrammatically: [C#] Choose BeginEditMode radPropertyGrid1.BeginEditMode = RadPropertyGridBeginEditModes.BeginEditOnClick; [VB.NET] Choose BeginEditMode RadPropertyGrid1.BeginEditMode = RadPropertyGridBeginEditModes.BeginEditOnClick 12. Next, we can choose which item to be selected when the control pops up, by assigning it to the SelectedGridItem property. Let's select the "Image" propety by default: [C#] Select item radPropertyGrid1.SelectedGridItem = radPropertyGrid1.Items["Image"]; radPropertyGrid1.PropertyGridElement.PropertyTableElement.ScrollToItem (radPropertyGrid1.Items["Image"]); [VB.NET] Select item RadPropertyGrid1.SelectedGridItem = RadPropertyGrid1.Items("Image") RadPropertyGrid1.PropertyGridElement.PropertyTableElement.ScrollToItem (RadPropertyGrid1.Items("Image")) 13. In order to customize the items appearance you should handle the ItemFormatting event of
288
289
290
291
19. One more thing to add isvalidation. Let's handle thePropertyValidating event to do that.There we will forbid habind a propertiy of type string with empty string value. To test this functionality in our example, add somevalue to the Text property and then try to remove it. [C#] Validating void radPropertyGrid1_PropertyValidating(object sender, PropertyValidatingEventArgs e) { PropertyGridItem item = e.Item as PropertyGridItem; if (item.PropertyType == typeof(string)) { if (string.IsNullOrEmpty(e.NewValue.ToString())) { item.ErrorMessage = "String value must not be an empty string!"; e.Cancel = true; } } } [VB.NET] Validating Private Sub radPropertyGrid1_PropertyValidating(ByVal sender As Object, ByVal e As
292
11.6 Summary
This chapter exploredhow to workwith RadPropertyGrid design time and how to take advantage of itsfunctionalities like grouping, sorting andfiltering. Furthermore, it showed how to customize the control appearance and also how to validate property values.
293
12.1 Objectives
Learn about the controls that have DataSource properties and the bindable types that can be assigned to them. Become familiar with binding to simple arrays and lists of objects. Use BindingSource to bind to database, business objects and web services. Bind to simple controls using the DataBindings property. Bind to LINQ data sources.
12.2 Introduction
Up till now we've had to populate controls explicitly, oneline of code at a time. Even the RadPageView "Custom Elements Walk Through" example where we populated a RadListControl withdirectory names had to be performed within a loop with each RadListDataItem being assigned properties from a column in the data. Here's how that looked: [VB] Populating a RadListControl Iteratively Dim directories As String() = Directory.GetDirectories(drive.ToString()) For Each directory As String In directories listControl.Items.Add(New RadListDataItem(directory)) Next [C#] Populating a RadListControl Iteratively string[] directories = Directory.GetDirectories(drive.ToString()); foreach (string directory in directories) { listControl.Items.Add(new RadListDataItem(directory)); } return listControl; } In contrast, data binding provides a consistent way of keeping a control and its data store synchronized. To data bind RadControls you assign the DataSource property.Here's how the same directory listing example above looks using data binding. [VB] Populating a List Box by Data Binding listControl.DataSource = Directory.GetDirectories("C:\") [C#] Populating a List Box by Data Binding listControl.DataSource = Directory.GetDirectories("C:\\"); If the DataSource is assigned a DataSet, you may need to assign the DataMember property to specify a data table within the DataSet. What Data Can I Bind? RadControls that have a DataSource property bind to any object that implements IList or IListSource. Those two interfaces are behind many familiar implementations that you can bind to: arrays, generic lists, data tables and views. Type Example
294
Array
DataTable
DataView
295
For simple binding scenarios, you can also use the DataBindings property available to all Windows Control descendants. To use DataBindings you need to describe the control property you want bound, the DataSource and the part of the DataSource you want bound to the control property. This can be done at design-time or in code. The example below shows the RadTextBox Text and Tag properties being bound to the "AlbumName" and "AlbumID" columns of the DataSource. [VB] Using DataBindings radTextBox1.DataBindings.Add("Text", table, "AlbumName") radTextBox1.DataBindings.Add("Tag", table, "AlbumID") [C#] Using DataBindings radTextBox1.DataBindings.Add("Text", table, "AlbumName"); radTextBox1.DataBindings.Add("Tag", table, "AlbumID"); How Does the Control Know What to Display? If there multiple columns of data, how does the control know what should be displayed? That aspect of binding is control-specific. Controls with relatively simple lists, e.g. RadListControl and RadDropDownList, have DisplayMember and ValueMember properties that correspond to the Text and Value properties of each item. The DisplayMember data is displayed in the control. ValueMember column data is stored and available programmatically. Typically ValueMember contains arecord ID used to retrieve associated data. ValueMember can also hold any object you care to put in it. In contrast, the RadGridView is designed to display many levels of master detail tables and to display multiple columns worth of data at one time for each table. Using the most minimal route to getting data in RadGridView you still assign the DataSource/DataMember properties. You can stop right thereand have all the columns in theDataSource displayed automatically. Thechapter on RadGridView willdetail how to customize each column and display master/detail tables.
296
DataSource Column Assignment You may have noticed in "What Data Can I Bind" above that DisplayMember is not always specified. If the data only has a single member, the data is displayed. Types other than string can alsobe displayed automatically, e.g. an array of DateTime values:
297
[VB] Automatically Assigning Columns Dim arr As DateTime() = {DateTime.Today.AddDays(-1), DateTime.Today, DateTime.Today.AddDays (1)} radListControl1.DataSource = arr [C#] Automatically Assigning Columns DateTime[] arr = { DateTime.Today.AddDays(-1), DateTime.Today, DateTime.Today.AddDays(1) }; radListControl1.DataSource = arr; Let's take one more look at a very simple "Product" object that contains an integer ID and Description string. [VB] The Product Class Public Class Product Public Sub New(id As Integer, description As String) ID = id Description = description End Sub Public Property ID() As Integer Get End Get Set End Set End Property Public Property Description() As String Get End Get Set End Set End Property End Class [C#] The Product Class public class Product { public Product(int id, string description) { ID = id; Description = description; } public int ID { get; set; } public string Description { get; set; } } If we create a list of products and bind to a RadControl without specifying a DisplayMember...
298
radListControl1.DataSource = products [C#] Binding the Products List List<Product> products = new List<Product>(); products.Add(new Product(1, "Jute Heather Cardigan")); products.Add(new Product(2, "Retro Cardigan")); products.Add(new Product(3, "Cashmere Cardigan")); radListControl1.DataSource = products; ...the Product object name will be displayed for each record as a string:
Now with the addition of DisplayMember... [VB] Binding the Products With DisplayMember Dim products As New List(Of Product)() products.Add(New Product(1, "Jute Heather Cardigan")) products.Add(New Product(2, "Retro Cardigan")) products.Add(New Product(3, "Cashmere Cardigan")) radListControl1.DataSource = products radListControl1.DisplayMember = "Description" radListControl1.ValueMember = "ID" [C#] Binding the Products With DisplayMember List<Product> products = new List<Product>(); products.Add(new Product(1, "Jute Heather Cardigan")); products.Add(new Product(2, "Retro Cardigan")); products.Add(new Product(3, "Cashmere Cardigan")); radListControl1.DataSource = products; radListControl1.DisplayMember = "Description"; radListControl1.ValueMember = "ID"; ...the Product "Description" column shows up in the list.
The ValueMember column is available whenever we access an item and examine the Value property. For example, if we add a SelectedIndexChange event handler to the RadListControl...
299
Interacting with Bound Data When you want the ability toadd, update and deletebound data, use an implementation of IBindingList such as BindingList<> or BindingSource. You can find the complete source for this project at: \DataBinding\VB|CS\BindingList The objects that populate the IBindingList should implement the INotifyPropertyChanged interface. INotifyPropertyChangedsupports the ListChanged event of BindingList and automatically refreshes bound controls, such as RadGridView, RadListControl, etc. To implement INotifyPropertyChangedyou only need to add a PropertyChanged event. [VB] Class with INotifyPropertyChanged Class [MyClass] Implements INotifyPropertyChanged #region INotifyPropertyChanged Members Public Event PropertyChanged As PropertyChangedEventHandler #End Region End Class [C#] Class with INotifyPropertyChanged
300
[VB] Using BindingList and INotifyPropertyChanged Imports Imports Imports Imports System System.ComponentModel System.Windows.Forms Telerik.WinControls.UI;
Namespace BindingList Public Partial Class Form1 Inherits Form Public Sub New() InitializeComponent()
301
302
303
304
This step will display the Data Source Configuration Wizard where you can connect to database data, business objects or services. 3. In the Data Source Configuration Wizard "Choose a Data Source Type" page, select the Database icon and click Next to continue.
305
4. In the "Choose Your Data Connection" page, click the New Connection button. This will display the Add Connection dialog. Note that you can also select an existing connection if you have already been through the configuration process and have a configuration that matches your needs. The Add Connection dialog will help us describe the kind of data (SQL Server, Access, etc.) and the location of the data. In the RadControls for WinForms installation directory you can find a series of Access (*.mdb) files in the /Examples/Datasources subdirectory. You can just as easily connect to SQL Server or other enterprise level data.
306
If the Data Source doesn't list "Microsoft Access Database File", then click the Change button, select it from the list in the Change Data Source dialog and click OK. Click the Browse... button and navigate to the RadControls for WinForms installation directory, locate the \Examples\DataSources directory and select the MusicCollection.mdb file. Click OK to close the Add Connection dialog.
307
6. In the Data Source Configuration Wizard "Choose Your Data Connection" page, click Next to continue. 7. A dialog will display asking if you want to copy this file locally. Select No to reference the database file in its original location. 8. In the "Choose Database Objects" page of the wizard, open up the treeview and select the tables and fields you want to include in your data source.
308
9. Click Finish to close the wizard. A DataSet object that encapsulates selected tables and fields is created automatically.
10. Back in the Properties window, locate the DataSource property for your control, drop down the list and select one of the tables as your data source.
309
This step will automatically create a series of components and drop them in your component tray:a DataSet component specific to the data you chose, a BindingSourceand a TableAdapter tohandle the lower level jobs of querying and updating your data.
A line of code is added to the form load event to populate the table with data: [VB] Automatically Generated Code Private Sub Form1_Load(sender As Object, e As EventArgs) ' TODO: This line of code loads data into the 'musicCollectionDataSet.Albums' table. You can move, or remove it, as needed. Me.albumsTableAdapter.Fill(Me.musicCollectionDataSet.Albums) End Sub [C#] Automatically Generated Code private void Form1_Load(object sender, EventArgs e) { // TODO: This line of code loads data into the 'musicCollectionDataSet.Albums' table. You can move, or remove it, as needed. this.albumsTableAdapter.Fill(this.musicCollectionDataSet.Albums); }
310
311
RadLabel: Text = "Album ID" RadTextBox: Name = "tbAlbumID", Text = "" RadLabel: Text = "Album Name" RadTextBox: Name = "tbAlbumName", Text = "
Click the tbAlbumID RadTextBox, navigate to the Properties window and in the "(Databindings)" property (aways at the top of the list), click the ellipses for the Advanced property.
312
In the Property list on the left of the dialog select the Text property. In the drop down under the label "Binding:", click the Add Project DataSource... link. This will bring up the Data Source Configuration wizard. Follow the steps in the "Getting Started" tutorial and configure the data source for all the columns in the Albums table. When you close the Data Source Configuration wizard, select the "Album" column of the "albumsBindingSource"as the data source.
Click the OK button to close the Advanced Formatting and Binding dialog. Notice that the (DataBindings) property has the Text property assigned "albumsBindingSource - AlbumID". Scroll down and also take a look at the Text Property. It will be marked with a small database icon with a tool tip that describes the binding.
3. Use the DataBindings property to bind the tbAlbumName property to the "AlbumName" column of the database.
313
4. Press Ctl-F5 to run the application. The data for the first record shows up in the bound text boxes.
Centralized control for binding operations. Unlike CurrencyManager, BindingSource works for complex binding scenarios. BindingSource encapsulates and is a replacement for CurrrencyManager.CurrencyManager can still be used directly, but BindingSource is easier to use and more flexible.
"Up-converts" non IBindingList data sources by copying elements into an internal IBindingList. This allows you to use data sources like SqlDataRead automatically. The IBindingList AddNew method canbe extended for custom implementations, for example so that factory objects can create new items in the list. Supports type based binding. You can assign a type instead of an instance and BindingSource will handle instance creation automatically. Simplifies binding to web services. Supports editing operations and events, e.g. RemoveCurrent, EndEdit, CancelEdit, Add and the CurrentItemChanged event. Can be visualized and managed with the BindingNavigator (VCR like UI that allows navigation and editing).
In the earlier example "Introduction", only the RadDropDownList and RadGridView are synchronized. This is because all the other controls use a DataSet or DataTable directly, but RadDropDownList and RadGridView both use "albumsBindingSource", a BindingSource instance. If we hook up all the controls on the page with the BindingSource, all controls are completely synchronized automatically. The example below takes the "Introduction" project, adds a BindingNavigator and points the DataSource property of all controls to "albumsBindingSource". The addition of the BindingNavigator just adds a UI control so
314
315
BindingNavigator: BindingSource = <the binding source component you just added> RadListControl: Name = "lbProducts" RadLabel: Text = "Description" RadTextBox: Name = "tbDescription" RadLabel: Text = "ID" RadSpinEditor: Name = "seID" RadButton: Name = "btnUpdate"
3. Add a new class "Product.cs" to the project and define the Product class.
316
317
318
319
The example shown here will be vastly simplified from a production level application in that the service will exist on the same machine as the WinForms application and in fact will be in the same Visual Studio solution and application domain. The example does not delve into the intricacies of WCF. Please refer to MSDN and other online sources for more about WCF. Also know thatthe paradigm used here (create a service, reference a service, use a service client to call service methods and return data) will all work similarly if instead you substitute the older standard web service instead of a WCF service. You can find the complete source for this project at:
320
1. Create a new Windows Forms Application. 2. In the Solution Explorer, right-click the solution and select Add | New Project from the context menu. Select the WCF Service Library project type, name the project "BindingToServices"and click OK to create the new service. This step will create a IService1.cs file that will contain the IService1 interface "contract" and Service.cs that will contain the implementation for the service methods. 3. In the code for IService1.cs, add a method called "GetList()" that will supply the data. Notice the "CompositeType" class defined further down in the IService1.cs file. GetList() will return a generic list of CompositeType. [VB] Adding the GetList() Method <OperationContract> _ Function GetList() As List(Of CompositeType) End Function [C#] Adding the GetList() Method [OperationContract] List<CompositeType> GetList(); 4. In the code for Service1.cs, add a GetList() method implementation to the Service1 class. The method creates several "CompositeType" instances, adds them to the list, then returns the list. WCF will automatically convert the GetList() generic list to an array of CompositeType. List<> is specific to .NET and using a simple array makes the method results accesible by a wider audience of clients. [VB] Adding the GetList() Implementation Public Function GetList() As List(Of CompositeType) Dim list As New List(Of CompositeType)() Dim composite1 As New CompositeType() composite1.StringValue = "One - From GetList()" list.Add(composite1) Dim composite2 As New CompositeType() composite2.StringValue = "Two - From GetList()" list.Add(composite2) Dim composite3 As New CompositeType() composite3.StringValue = "Three - From GetList()" list.Add(composite3) Return list End Function [C#] Adding the GetList() Implementation public List<CompositeType> GetList() { List<CompositeType> list = new List<CompositeType>(); CompositeType composite1 = new CompositeType(); composite1.StringValue = "One - From GetList()"; list.Add(composite1); CompositeType composite2 = new CompositeType(); composite2.StringValue = "Two - From GetList()";
321
322
323
This is where BindingSource comes to the rescue again. It createsan IList behind-the-scenes and loads the IEnumerable based results into the list.
Now the code has the intermediate step of creating the BindingSource. In the constructor, pass the LINQ results. The second constructor argument is the data member and can be left blank. [VB] Using BindingSource With LINQ Results Dim products As New BindingList(Of Product)() products.Add(New Product(1, "Coffee", 1.4)) products.Add(New Product(2, "Latte", 2.4)) products.Add(New Product(3, "Mocha", 2.7)) products.Add(New Product(4, "Espresso", 2.5)) products.Add(New Product(5, "Tea", 1.3)) products.Add(New Product(6, "Chai", 1.5)) products.Add(New Product(7, "Cafe au Lait", 1.5)) Dim productQuery As IEnumerable(Of Product) = From product In products _ Where product.Description.StartsWith("C") _ Where product.Price > 1.49 _ Order By product.Description _ Select product radListControl1.DataSource = New BindingSource(productQuery, "") radListControl1.DisplayMember = "Description" radListControl1.ValueMember = "ID" [C#] Using BindingSource With LINQ Results BindingList<Product> products = new BindingList<Product>(); products.Add(new Product(1, "Coffee", 1.40)); products.Add(new Product(2, "Latte", 2.40)); products.Add(new Product(3, "Mocha", 2.70)); products.Add(new Product(4, "Espresso", 2.50)); products.Add(new Product(5, "Tea", 1.30));
324
You can find the complete source for this project at: \DataBinding\VB|CS\BindingImages 1. Start with the "Getting Started" project or a copy. 2. In the Solution Explorer, right-click the project and select Add | New Item... from the context menu, thenselect Telerik RadForm and click the Add button.
325
326
327
12.10Binding RadGridView
RadGridView is sucha control that is usedin mopsbusiness applications that we should take a walkthrough of binding the grid to database data. This example will demonstrate binding to a single database table. See the upcoming chapter "Grid" for more information on binding to hierarchical data and binding to Dynamic LINQdata. You can find the complete source for this project at: \Databinding\VB|CS\GridView Please note that this example assumes that you have installed Northwind database on your local sql server. 1. In a new Windows Forms Application, drop a RadGridView on the default form. 2. From the grid Smart Tag, drop down the Choose DataSource list and select Add Project Data Source...
3. In the Data Source Configuration Wizard "Choose a Data Source Type" page, select the Database icon and click Next to continue.
328
4. In the "Choose Your Data Connection" page, click the New Connection button.
329
Click the Change... button to display the Change Data Source dialog, select the MS SQL Server datasource type and click OK to close the dialog. Enter ".\SQLEXPRESS" as the Server Name and select "AdventureWorks" as the database name. Click OK to close the Add Connection dialog.
330
6. In the Data Source Configuration Wizard "Choose Your Data Connection" page, click Next to continue. 7. In the Data Source Configuration Wizard "Save the Connection String to the Application Configuration File" page, clickNext to continue. 8. In the "Choose Database Objects" page of the wizard, open up the treeview and select the tables and fields you want to include in your data source. For the sake of this example, choose all the fields of the "SalesPerson" table.
331
9. Click Finish to close the wizard. A DataSet object that encapsulates selected tables and fields is created automatically. Also, a line of code is placed in the Form's Load event handler that fills the SalesPerson table in the dataset.
10. For a minimal implementation, this is all that's needed to bind the grid to a database file. Press Ctrl-F5 to run the applicaiton and view the data. Note: The example below adds a "BreezeTheme" component to the form and sets the RadGridView Theme property to "Breeze".
332
In the upcoming "Grid" chapter you will learn how to extend this example to manipulate rows and columns, bind hierarchical data and much more.
12.11Summary
In this chapter you learned which controls have DataSource properties and the bindable types that can be assigned to them. The chapter started out by showing examples of binding to simple arrays and lists of objects, then went on to use BindingSource to bind to database, business objects and web services. The chapter also showed how to bind to simple controls using the DataBindings property. Finally you learned how to bind to LINQ data sources.
333
13.1 Objectives
Learn how to provide user feedback using RadStatusStrip, RadTrackBar, RadWaitingBar, RadProgressBar and RadLabel controls. Learn usage and basic characteristics for each type of control. Learn how to add items to the RadStatusStrip Items collection. Programmatically add items and hosted items to the status strip. Learn how to coordinate long running background processes with the waiting bar and progress bar.
13.2 Introduction
If half the UI battle is to retrieve information from the user, the other half is to provide feedback. The user needs to know what just happened, what's going on now and what's coming up next. Applications with strong feedback keep the user involved and oriented within the overall process. Over time a number of UI conventions for feedback have evolved that are encapsulated within controls. The most basic is the general purpose label that can be updated to notify the user of changes. RadLabel is a themable label that coordinates nicely with other themed controls like this example where the RadForm, RadButton and RadLabel are all set to the "Desert" theme.
RadProgressBar and RadWaitingBar are used to provide feedback for long running operations. RadTrackBar can be used to collect input and to visually represent a numeric value within a range.
RadStatusStrip can be used both as a feedback mechanism and a menu. The status strip can contain feedback elements, i.e. label, progress bar, waiting bar and even track bars as well as various button types and can also host any Control descendant.
334
335
After you've dragged the images into the Resources.resx editor, right-click and Rename to the spelling and case shown in the list above. In later sections of this chapter you will want to reference these images using the syntax "Properties.Resources.Error" --the spellings of each image resource object in Properties.Resources is case sensitive. 7. Change the project to start with RadForm1 instead of Form1.
336
RadButtonElement: Name = "btnServers", Text = "Find Servers", TextImageRelationship = "ImageBeforeText. RadLabelElement: Name = "lblStatus", Text = "", Spring = "True", TextImageRelationship = "ImageBeforeText. RadLabelElement: Name = "lblHost", Text = "", AutoSize = "False", Size = "54, 54". RadProgressBarElement: Name = "pbStatus", Alignment = "BottomCenter",MaxSize = 0,23, Spring = True.
3. In the area above the status strip add the following controls and set properties:
337
RadListControl: Name = "lcServers", Anchor = "Top, Left, Right". RadLabel: Text = "Databases". RadListControl: Name = "lcDatabases",Anchor = "Top, Left, Right". RadPanel: Name = "pnlMaxObjects", Anchor = "Top, Right" On the RadPanel, add the following:
RadLabel:Text = "Max Objects". RadTrackBar: Name = "tbMaxObjects", Maximum = "100", BackColor = "Transparent", ShowTicks = "False", SliderAreaColor1 = "PaleTurquoise", SliderAreaColor2 = "SteelBlue", ThemeName = "Aqua", TicksColor = "Transparent". RadLabel: Name = "lblCount", BackColor = "Transparent", Text = "0".
338
339
The RadStatusStrip Smart Tag has an additional "Edit Items" link that invokes the RadItems collection editor dialog. TheSmart Tag also has a "Dock in parent container" link.
Tasks
From the Smart Tag Tasks menu you can select New Theme Manager to add a Theme Manager component to the component tray, Edit UI elements to browse all of the elements of the button and to change properties for any element. The Theme Name drop down lets you pick an existing theme to style your control.
340
Search
Enter search criteria in the edit space provided and click the Search link to navigate directly to search on the Telerik web site.
...Orclick the drop down button arrow to select from one of the element types. The types listed in the drop down will be the same item types available in the RadItem Collection editor dialog. To get to the dialog click the Smart Tag "Edit Items" link or click the Items property ellipses in the Property window.
Properties
RadLabel
RadLabel works as a themable alternative to a standard Label control. The example below shows a standard label with the Image property set to a picture of an Antelope and the Text aligned MiddleCenter. The RadLabel has the BackgroundImage set to the same picture and the Image property set to the picture of a 16 x 16 globe. TheImageAlignment property is BottomRight,TextImageRelation set to TextAboveImage and the ThemeName is "Desert".
341
RadWaitingBar
Use RadWaitingBar to let your user know something is happening, but you don't know how long the process will take. Connectivity to network or database resources can fall into this category. As your network API method casts around looking for servers or IP addresses, the API may find 10 or 100 available. There is no way to know ahead of time. RadWaitingBar uses the StartWaiting() method to animate the waiting bar and EndWaiting() to cease animation.
Orientation can be Vertical or Horizontal. Using Vertical orientation, the thumb moves from top to bottom down the bar. WaitingIndicatorWidth isthe width of the thumb. WaitingSpeed sets the speed of the animation. Higher numbers move the thumb more quickly across the bar. WaitingStep is the number of pixels the thumb moves in each step. The default is "1" and provides a smooth animation. Larger number may appear "jumpy".
RadProgressBar
Unlike RadWaitingBar, RadProgress bar lets the user know where they are within a process and to get a good feel for about how long the process will take to complete. RadProgressBar lets you set and display two different progress indicators independently, Value1 and Value2. The Theme will determine how the two values are displayed, or even if Value2 will be visible. This screenshot shows a RadProgressBar with the "Desert" theme, Value1 = "50" and Value2 = "70".
Dash and Hatch properties control the drawing style of the active portion of the progress bar. If Dash is set to False (whatever the Hatch setting), the active portion of the progress bar will be drawn in a solid color set by the BackColor property. If Dash is set to True and Hatch is set to False, the active portion of the progress bar will be draw in a striped pattern. The stripes will fade from the Separator1 color to the Separator2 color. If Dash is set to True and Hatch is set to True, the active portion of the progress bar will be drawn in a cross-hatched pattern. The cross hatches will fade from the Separator1 color to the
342
SeparatorWidth controls the width of the stripes or cross hatches in the active portion of the progress bar. StepWidth controls the spacing between the stripes or cross hatches in the active portion of the progress bar. SweepAngle sets the angle of the stripes or cross hatches in the active portion of the progress bar. BackColor sets the color of the control background where the progress bar isn't being painted. Depending on the theme, you may or may not be able to see this color. ForeColor is the color of the text that reports the completion percentage or the Text. Minimum and Maximum properties set the allowed range of values for the Value1 and Value2 properties. ProgressOrientation represents the direction that the progress bar moves. You can set this property to Top, Left, Right, or Bottom to display progress starting at the top, left, right, or bottom of the control. ShowProgressIndicators when true replaces the Text with the percentage of completion.
RadTrackBar
RadTrackBar can be used both to input numeric values and to indicate the current status of a numeric value within a range. When working programmatically with RadTrackBar, use the ValueChanged event to detect that the user has moved the slider. The Value property indicates the current position of the slider.
ShowSlideArea controls whether the line down the middle of the control where the slider rides is visible. ShowTicks controls whether tick marks are drawn. TicksColor sets the color of the tick marks, TickFrequency sets the spacing of the tick marks and TickStyle controls whether the tick marks are drawn on one or both sides of the control. SlideAreaWidth property sets the width of the slide area in pixels. SlideAreaColor1, SlideAreaColor2, and SlideAreaGradientAngle properties control the way that the slide area is shaded.
343
ThumbWidth sets the width of the slider thumb LargeChange is the change in value that one click of the mouse outside of the slider makes. Minimum and Maximum limit the Value property. Orientation can be set to Horizontal or Vertical.
In the example above Orientation is Vertical, Maximum is "100" and the Value is "80". SliderAreaColor1 is "LightGray", SliderAreaColor2 is "Red" and SliderAreaGradientAngle is "320". SliderAreaWidth is "10", making it wide enough to see the color gradient. TickFrequency is "10", spacing out the ticks to be easily visible. TickColor is "Maroon" and TickStyle is "BottomRight". the theme is Office2007Silver and finally from the smart tag select the EditUI elements, navigate to TrackBarThumb and set itsAngleTransform to 0. Now click on the track bar smart tag and select Edit UI elements. Select the TrackBarPrimitive and set its BackColor to Control,BackColor2 to ControlDark and GradientStyle to Linear. Finally select the TrackBarThumb element and change its AngleTransform property to 0.
344
345
So how do we update a progress bar as work processes and avoid threading clashes? There are multiple methods available to synchronize threads that can be appropriate. The BackgroundWorker component has a ProgressChanged event that is ideal for this situation. You will need to set the BackgroundWorker WorkerReportsProgress property to true and call the ReportProgress() method. Notice in particular that the ProgressChanged event has been hooked up to a handler and the WorkerReportsProgress property is set to true. [VB] Adding The ProgressChanged Event Private Sub btnServers_Click(sender As Object, e As System.EventArgs) lblStatus.Text = "Finding..." Dim worker As New BackgroundWorker() worker.RunWorkerCompleted += New RunWorkerCompletedEventHandler(worker_RunWorkerCompleted) worker.DoWork += New DoWorkEventHandler(worker_DoWork) worker.WorkerReportsProgress = True worker.ProgressChanged += New ProgressChangedEventHandler(worker_ProgressChanged) worker.RunWorkerAsync() End Sub [C#] Adding The ProgressChanged Event private void btnServers_Click(object sender, System.EventArgs e) { lblStatus.Text = "Finding..."; BackgroundWorker worker = new BackgroundWorker(); worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted); worker.DoWork += new DoWorkEventHandler(worker_DoWork); worker.WorkerReportsProgress = true; worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged); worker.RunWorkerAsync(); } Gotcha! Attempting to use the ProgressChanged event without setting WorkerReportsProgress to true will generate an exception.
Inside the DoWork event handler call ReportProgress() every time you want to update the user interface. Pass an integer representing the percentage of progress achieved and a UserState object that can contain any arbitrary data. Notice that there is no UI related code inside the DoWork event handler -- that is for the ProgressChanged event to take care of. At the conclusion of DoWork assign the Result argument property. This value can be retrieved later in the RunWorkerCompleted event.
346
347
348
349
350
[C#] Adding References System; System.Collections.Generic; System.ComponentModel; System.Data; System.Drawing; System.Windows.Forms; Microsoft.SqlServer.Management.Smo; Telerik.WinControls; Telerik.WinControls.Primitives; Telerik.WinControls.UI;
3. Add an enumeration that will be used later when displaying status information: [VB] The StatusTypes Enumeration Enum StatusTypes Info [Error] Find End Enum [C#] The StatusTypes Enumeration enum StatusTypes { Info, Error, Find }; 4. Add a private member that will store a list of DatabaseInfo objects and a RadLabelElement that will host our waiting bar control. [VB] Generic List of DatabaseInfo Private _dbInfoList As List(Of DatabaseInfo) Private _waitingBarHostLabel As RadLabelElement [C#] Generic List of DatabaseInfo private List<DatabaseInfo> _dbInfoList; private RadLabelElement _waitingBarHostLabel; 5. Add the helper methods below. The helper methods will:
Get an icon representing a given StatusTypes member. Display status messages and icons. Show/Hide both the progress and waiting bars. Toggle the UI Enabled properties to prevent the user from initiating new processes before existing
351
352
353
354
6. Replace the code in the Form's Load event handler with the code below. The first line of code here will simply give the "Max Objects" panel rounded corners. Then create a RadLabelElement that hosts the waiting bar. Finally, hide the progress bar until needed. [VB] Handling the Form Load Event
355
List Servers
1. To handle tasks related to the BackgroundWorker for the list of servers, add the code below.
RunServerWorker() creates the BackgroundWorker object instance, hooks up the events and calls RunWorkerAsync() to begin processing. The DoWork() event handler calls the SmoApplication static EnumAvailableSqlServers() method. The task of retrieving any available MS SQL servers takes an unknown amount of time so the waiting bar is the most appropriate control to display feedback. The RunWorkerCompleted() event handlergets the result containing a DataTable with the list of databases anddisplays a completion method, or displays an error message if an exception occurs. Exceptions thrown in DoWork() are passed to RunWorkerCompleted in the argument Error property. [VB] Handle the Server BackgroundWorker ' create and configure the BackgroundWorker object Private Sub RunServerWorker() Dim serverWorker As New BackgroundWorker() serverWorker.DoWork += New DoWorkEventHandler(serverWorker_DoWork) serverWorker.RunWorkerCompleted += New RunWorkerCompletedEventHandler (serverWorker_RunWorkerCompleted) serverWorker.RunWorkerAsync() End Sub ' retrieve MS SQL servers, pass back DataTable result Sub serverWorker_DoWork(sender As Object, e As DoWorkEventArgs) e.Result = SmoApplication.EnumAvailableSqlServers() End Sub ' update the UI using the Result property of the args, or ' the Error property if the operation fails. Sub serverWorker_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) If e.[Error] <> Nothing Then DisplayStatus(e.[Error].Message, StatusTypes.[Error]) Else ' populate list control from data table of servers passed in as Result Dim dt As DataTable = TryCast(e.Result, DataTable) For Each row As DataRow In dt.Rows
356
357
Try testing the exception handling portion of code by deliberately throwing an Application exception during the DoWork event handler. The RunWorkerCompleted event will fire and e.Error will contain the Exception object. [VB] Triggering an Exception Sub serverWorker_DoWork(sender As Object, e As DoWorkEventArgs) Throw New ApplicationException("Something bad happened") e.Result = SmoApplication.EnumAvailableSqlServers() End Sub [C#] Triggering an Exception void serverWorker_DoWork(object sender, DoWorkEventArgs e) { throw new ApplicationException("Something bad happened"); e.Result = SmoApplication.EnumAvailableSqlServers(); } If you are debugging, Visual Studio will break at the line that causes the exception. Press Ctrl-F5 to continue to the RunWorkerCompleted event handler.If you're not debugging you should see the exception message displayed in the status strip immediately.
358
RunDBWorker() creates the BackgroundWorker object instance, hooks up events and calls RunWorkerAsync() to begin processing. Notice that the WorkerReportsProgress property is set to true and the ProgressChanged event is assigned a handler. The server name is passed to the RunWorkerAsync() method. The DoWork() event handler retrieves and processes the list of databases on the server. During processing the event handler tracks the minimum and maximum number of objects for all databases. As each database is processed, a DatabaseInfo object is created, saved in a listand sent through to the ReportProgress() method. When all processing is complete, a DBWorkerResult object is created, populated and sent back in the arguments Result property. The RunWorkerCompleted() event handlergets the result containing the DBWorkerResult and the information is used to update the UI. [VB] Handle the Server BackgroundWorker ' create and configure BackgroundWorker. Populate and pass server name as argument. ' enable progress reporting Private Sub RunDbWorker(serverName As String, maxObjects As Integer) Dim dbWorker As New BackgroundWorker() dbWorker.WorkerReportsProgress = True dbWorker.DoWork += New DoWorkEventHandler(dbWorker_DoWork) dbWorker.ProgressChanged += New ProgressChangedEventHandler(dbWorker_ProgressChanged) dbWorker.RunWorkerCompleted += New RunWorkerCompletedEventHandler (dbWorker_RunWorkerCompleted) dbWorker.RunWorkerAsync(serverName) End Sub ' retrieve the list of databases for the server: ' -get the number of objects for each database, ' -keep track of the min and max number of objects. ' -calculate progress, ' -create and populate a DatabaseInfo object and pass to ' ProgressChanged event handler. ' Create and populate a DBWorkerResult object and assign to the arguments ' Result property. Sub dbWorker_DoWork(sender As Object, e As DoWorkEventArgs) Dim server As New Server(serverName) Dim count As Integer = 0 Dim maxObjectCount As Integer = 0 Dim minObjectCount As Integer = 0 For Each database As Database In server.Databases System.Math.Max(System.Threading.Interlocked.Increment(count),count - 1) ' ignore empty databases If database.IsAccessible Then ' get all objects in the database Dim dtObjects As DataTable = database.EnumObjects() ' calculate progress Dim progress As Integer = DirectCast(((DirectCast(count, Double) / DirectCast (server.Databases.Count, Double)) * 100), Integer) ' assign the first non-zero value If (minObjectCount = 0) AndAlso (dtObjects.Rows.Count > 0) Then minObjectCount = dtObjects.Rows.Count End If
359
360
361
362
363
Respond to Events
Two more events still need to be handled, the SelectedIndexChanged for the database list control and the ValueChanged event handler needs to be replaced with new code. 1. Create a SelectedIndexChanged event handler for "lbDatabases" and add the code below. This code retrieves the DatabaseInfo object that's stored in the Value property of the selected item. The server name, database name and number of objects are displayed in the status strip. Notice that the RadLabelElement in the status strip displays text on multiple lines. [VB] Handling the SelectedIndexChanged Event for the Database List Control Private Sub lbDatabases_SelectedIndexChanged(ByVal sender As Object, ByVal e As Telerik.WinControls.UI.Data.PositionChangedEventArgs) Handles lbDatabases.SelectedIndexChanged If Not (TryCast(sender, RadListElement)).SelectedValue Is Nothing Then Dim info As DatabaseInfo = TryCast((TryCast(sender, RadListControl)).SelectedValue, DatabaseInfo) Dim message As String = String.Format("{0}\{1}{2}{3} objects", info.ServerNameProp, info.DatabaseNameProp, Environment.NewLine, info.ObjectCountProp) DisplayStatus(message, StatusTypes.Info) End If End Sub [C#] Handling the SelectedIndexChanged Event for the Database List Control private void lbDatabases_SelectedIndexChanged(object sender, Telerik.WinControls.UI.Data.PositionChangedEventArgs e) { if ((sender as RadListElement).SelectedValue != null) {
364
13.6 Summary
365
366
14.1 Objectives
Learn how to create rows and strip with elements in RadCommandBar Learn how to add items to the strip. Programmatically create and add rows, strips and items. Learn how to customize the appearance of the command bar items.
14.2 Introduction
RadCommandBar is a fully theme-able tool strip that provides unprecedented flexibility. More than just a collection of buttons, RadCommandBar hosts any RadControl, including combo boxes, text boxes, split buttons, drop-down buttons, toggle buttons and more. CommandBar can be moved, rearranged and resized at run time for easy end-user customization. RadCommandBar can be styled to match any user interface using a predefined theme or a theme you design yourself using the Visual Style Builder.
RadCommandBar supports horizontal and vertical orientation.CommandBarStrip areascan be dragged within the CommandBarRows or it can be floated off the form.
The overflow button automatically displays items that don't have the real estate to display by default. The end user can also customize the strips by adding and removing buttons.
367
Structure
RadCommandBar is built up of four levels of nested components:
The CommandBarStripElement represents a horizontal band within the RadCommandBar where command bar items are displayed. CommandBarStripElement is associated with a particular CommandBarRowElement but it may be relocated at design or at run time.
The CommandBarItems represents a items within a CommandBarStrips. The individual items are shown in the drop down list in the screenshot below. Of course, custom controls can be hosted too.
368
369
New Open Save Print Help You can typically find images in the Visual Studio Common7\VS2008ImageLibrary\1033 directory in "VS2008ImageLibrary.zip".
Form Setup
1. From the Toolbox, add a RadCommandBar to the form.Point the ImageList property at the ImageList component that you added earlier. 2. Add a RadStatusStrip to the form. It will automatically dock to the bottom. Point the ImageList property at the ImageList component that you added earlier. 3. Drop a standard Windows RichTextBox control below the RadCommandBar. Set the Dock property to "Fill".
CommandBarConfiguration
1. When RadCommandBar was created it automatically populates itself with one CommandBarRowElement and one CommandBarStripElement. 2. In design-time click the "Click here to add new row." to create second row in RadCommandBar.
3. Click the plus image next to the first strip on the first row to create second CommandBarStrip on the first row. Also click the plussign on the second row to create strip element there too.
370
Add Items
1. Click the first CommandBarStripElement and from the drop down select CommandBarButton. Set the followingCommandBarButton properties:
371
Name = "btnNew" ToolTipText = "File New" ImageIndex = <ImageList image that represents "New">
2. Create another CommandBarButton from the dropdown and set the following properties:
Name = "btnOpen" ToolTipText = "File Open" ImageIndex = <ImageList image that represents "Open">
3. Create another CommandBarButton from the dropdown menu and set following properties:
Name = "btnSave" ToolTipText = "File Save" ImageIndex = <ImageList image that represents "Save">
4. Click the second strip element amd create a CommandBarButton with the following properties:
Name = "btnPrint" ToolTipText = "Print" ImageIndex = <ImageList image that represents "Print">
Name = "tbTwoSidedPrint" ToolTipText = "Two Sided Print" Text = "Two Sided Print" DrawText = true Image = ""
372
6. On the second row of add a new CommandBarButton with the following properties
Name = "btnHelp" ToolTipText = "Help" ImageIndex = <ImageList image that represents "Help"> Here is how your project will look like at this point.
373
374
Adding rows
You can add CommandBarRowElements by clicking on the "Click here to add new row" on the design time surface, by selecting "Add Row" from RadCommandBar Smart Tag or by editing the CommandBarRowElementCollection again from the Smart Tag.
Adding strips
Strips are added by clicking the plus sing on the design time surface, by selecting "Add New Strip" from the CommandBarRowElement Smart Tag, or by editing the CommandBarStripElementCollection from the Smart Tag
375
Adding items
Visually designing the RadCommandBar begins at the design time surface where you canclick the dropdown arrow button to bring up the drop down with available CommandBarItems or use the Smart tag of the strip element and click the "Edit Items" to bring up the RadCommandBarBaseItemCollecition editor.
376
In either case, all the elements and items are available for editing in the Properties window.
RadCommandBarProperties
EnableDragging property allows the user to move the CommandBarStripElement within the strip using the element's drag handles.
377
To make the command bar items sit in larger strip, use the MinSize property. The screenshot below shows a CommandBarButton with a MinSize of50, 50, the CommandBarStripElement that the button is sitting on has MinSize 100, 100.
Modifing the visibility of the OverflowButton is set from the Properties window of the desired strip. Expand the OverflowButton and set the Visibility property to Collapsed to hide it. The orientation of RadCommandBar it set automatically, when the Dock property is changed.
378
14.5 Programming
Building RadCommandBar Items Programmatically
Building strips in code follows the same pattern as working in the designer. The hierarchy is: RadCommandBar CommandBarRowElement[] CommandBarStripElement[] CommandBarItem[] This next demo shows how to add everything in RadCommandBar. The empty command bar will be docked to the top of the form. A number of icons have been loaded into the Solution Explorer Properties | Resources and will be used to populate items. You can find the complete source for this project at: \CommandBar\<VB|CS>\Programming In the form load,create an instance of RadCommandBar and add it to the controls collection of the form. Create a CommandBarRowElement, set its Dock property to "Top"and add it to the Rows collection of RadCommandBar. Then create an instace of CommandBarStripElement and add it to the Strips collection of the created row element. Finally call the LoadItems method, which we will implement next. [VB] Building the CommandBar Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Dim radCommandBar1 As New RadCommandBar() radCommandBar1.Dock = DockStyle.Top radCommandBar1.Name = "radCommandBar1" Me.Controls.Add(radCommandBar1) Dim commandBarRowElement1 As New CommandBarRowElement() commandBarRowElement1.Name = "commandBarRowElement1" radCommandBar1.Rows.Add(commandBarRowElement1)
379
380
381
The example below shows the general approach for saving and loading the tool strip layout. You will probably want to make changes in the storage medium used to contain the XML (e.g. database, isolated storage, etc.). You will also need additional safety code to prevent or handle partial serialization resulting in corrupt XML. Lets continue with the previous project. Move the instance of the RadCommandBar outside the Load event handler in order to be able to access it from other places. Add two RadButtons to the form and set their text to "Save Layout" and "Load Layout" and theirnames to btnSave and btnLoadrespectively. Click both of them in
382
To recreate the RadCommandBar state at the time it was saved, pass the XML file to the LoadLayout method of the control. [VB] Restoring the Layout Private Sub btnLoad_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnLoad.Click Dim s As String = "default.xml" Dim dialog As New OpenFileDialog() dialog.Filter = "xml files (*.xml)|*.xml|All files (*.*)|*.*" dialog.Title = "Select a xml file" If dialog.ShowDialog() = DialogResult.OK Then s = dialog.FileName End If
383
14.6 Summary
In this chapter you learned how to build a command bar strips at design time and programmatically at run time. You exploredfloating and overflow behavior. You learned how to configure strip dimensioning, orientation and layout. Finally, you learned how to save and load the RadCommandBar layout.
384
15.1 Objectives
Learn how the special RadForm, ShapedForm and RadRibbonForm classes can be inherited from to create themable, custom shaped forms. Learn how Visual Studio project item templates are used to create instances of each form class. See how RadTitleBar is used with RadForm as a replacement for the built-in Windows form title bar. Learn how to use the RadMessageBox as a themable replacement for the standard MessageBox.
15.2 Introduction
The RadForm control allows you to design a styled Windows form with rounded corners. Use the pre-defined themes to quickly build a user interface that has a sharp, unified look-and-feel. The control comes with integrated TitleBar, support for Multiple Document Interface (MDI) applications and languages that require right-to-left layout.The RadControls for WinForms installation includes templates for RadForm and ShapedForm and specially configured RadForm types RadRibbonBarForm and RadAboutBox for greater productivity.
Use the ShapedForm to design and display a Windows form with any conceivable shape.
385
Use the handyRadMessageBox class to display modal dialog boxes that show status information or a requests for confirmation.RadMessageBox dialogs can be configured to display with captions, message text, icons and button sets.
386
CommandBarButton: Name = "btnRadForm", TextImageRelation = "ImageAboveText", Text = "RadForm", Image = <import an image that represents a form>. CommandBarButton: Name = "btnShapedForm", TextImageRelation = "ImageAboveText", Text = "ShapedForm", Image = <import an image that represents a form>. CommandBarButton: Name = "btnRadRibbonBar", TextImageRelation = "ImageAboveText", Text = "RadRibbonBar", Image = <import an image that represents a form>.
387
CommandBarButton: Name = "btnRadAboutBox", TextImageRelation = "ImageAboveText", Text = "RadAboutBox", Image = <import an image that represents a form>. CommandBarButton: Name = "btnRadMessageBox", TextImageRelation = "ImageAboveText", Text = "RadMessageBox", Image = <import an image that represents a form>.
4. Add a RadStatusStrip to the form. It will automatically dock to the bottom of the form. Add a single RadLabelElement to the status strip and set Name = "lblStatus", Spring = "True".
In the Solution Explorer, right-click the project and select Add | New Item... from the context menu. Select the "Telerik RadForm" template and click the Add button to close the dialog.
In the Solution Explorer, right-click the project and select Add | New Item... from the context menu. Select the "Telerik ShapedForm" template and click the Add button to close the dialog.
In the Solution Explorer, right-click the project and select Add | New Item... from the context menu. Select the "Telerik RadRibbonBar" template and click the Add button to close the dialog.
In the Solution Explorer, right-click the project and select Add | New Item... from the context menu. Select the "Telerik RadAboutBox" template and click the Add button to close the dialog.
388
389
390
391
ShapedForm
Unlike RadForm, ShapedForm actually descends from a standard windows Form. Shaped form comes with a RadTitleBar so the user can move, close, minimize and maximize the form. Both the RadTitleBar and the ShapedForm by default eachhave their Shape property set to RoundRectShape components. You can also use one of the predefined shapes, i.e.DonutShape, MediaShape, EllipseShape, QAShape, RoundRectShape, OfficeShape, TabIEShape, TabOffice12Shape, TabVsShape, TrackBarDThumbShape, TrackBarUThumbShape, TrackBarLThumbShape, and TrackBarRThumbShape. Or you can createyour own custom shape using the Shape Editor tool. In order to hide the default titlebar, the ShapedForm class has the FormBorderStyle property set to None while the RadForm FormBorderStyle property by default is set to Sizable. This mayimpact form behavior in some cases. RadTitleBar is also available as a separate RadControl in the ToolBox that can be dropped on any standard Form, ShapedForm or RadForm. The example screenshot below shows aShapedForm and RadTitle, both with their own custom shapes.
ShapedForm treats the whole space as its client area. When you dock a control in the form, it can cover the border of the window and disable form resizing. You can change the form Padding to make sure this area stays clear, oranchor a panelthat will contain all the controls forthe form.
RadAboutBox
The RadAboutBox has a little extra code to access the assembly you're running and will display all that information automatically in the about box along with an icon.
392
RadRibbonForm
RadRibbonForm comes pre-configured with a RadRibbonBar and a RadStatusStrip so that you don't have to spend time setting up this first layer of the UI.
RadMessageBox
RadMessageBox is a flexible, themeable, and not-to-mentionquite handy replacement for a standard Windows MessageBox. Some of the advantages to using RadMessageBox over MessageBox:
393
Like MessageBox, there's no design-time component involved. Use RadMessageBox Static methods SetTheme() to theme the dialog so it will blend with your application and call one of the many Show() method overloads to display the dialog. The minimal overload usage of Show() simply takes some message text:
[VB] Calling SetTheme() Private Sub btnRadMessageBox_Click(sender As Object, e As EventArgs) RadMessageBox.SetThemeName("Office2007Silver") 'or RadMessageBox.SetThemeName("Office2007Black") RadMessageBox.Show("Hello World!") End Sub [C#] Calling SetTheme() private void btnRadMessageBox_Click(object sender, EventArgs e) { RadMessageBox.SetThemeName("Office2007Silver"); //or RadMessageBox.SetThemeName("Office2007Black"); RadMessageBox.Show("Hello World!"); } You can add a caption that displays in the title bar of the dialog:
[VB] Show() With Caption Private Sub btnRadMessageBox_Click(sender As Object, e As EventArgs) RadMessageBox.Show("Server access will be interupted until 2pm (PST)", "System Message") End Sub [C#] Show() With Caption private void btnRadMessageBox_Click(object sender, EventArgs e) { RadMessageBox.Show("Server access will be interupted until 2pm (PST)", "System Message"); } As with MessageBox, evaluate the DialogResult return value from Show() to respond to user button selections. Here's an example that uses a more complex overload of the Show() method to include a predefined set of buttons, a system icon and the button that will be default if the user hits Enter instead of clicking with the mouse.
394
[VB] Getting User Feedback Private Sub btnRadMessageBox_Click(sender As Object, e As EventArgs) Dim result As DialogResult = RadMessageBox.Show("Go online to register?", "Registration", MessageBoxButtons.YesNo, RadMessageIcon.Question, MessageBoxDefaultButton.Button1) ' do something... If result = DialogResult.Yes Then End If End Sub [C#] Getting User Feedback private void btnRadMessageBox_Click(object sender, EventArgs e) { DialogResult result = RadMessageBox.Show( "Go online to register?", "Registration", MessageBoxButtons.YesNo, RadMessageIcon.Question, MessageBoxDefaultButton.Button1); if (result == DialogResult.Yes) { // do something... } }
Localization
If you need to localize or otherwise customize the text for a RadMessageBox, you can create your own RadMessageLocalizationProvider and assign it to be the current provider.
[VB] Custom Localization Provider Class and Assignment Public Class MyMessageLocalizationProvider Inherits RadMessageLocalizationProvider Public Overloads Overrides Function GetLocalizedString(id As String) As String Select Case id Case RadMessageStringID.AbortButton Return "Hold it!" Case RadMessageStringID.CancelButton Return "Lets not"
395
396
Assigning shapes to a ShapedForm, RadPanel and RadButton. Using BindingSource methods to navigate a dataset and to bind both image and text properties. Working with gradient styles of a fill primitive to achieve a glassy, translucent button and where the button color overtones match the image background. Using RadMessageBox to display a message and a specific bitmap thumbnail.
397
5. Add a RadPanel centered on the lower part of the donut shape. Set the Name property of the panel to "pnlTitle". Set the Size property to "200, 30".
6. Using the Smart Tag, select the Edit UI Elements link to bring up the Element Hierarchy Editor:
Select the RadPanelElement from the Control element structure treeview. Set the Shape property to "RoundRectShape" Open up the Shape property and set the Radius sub-property to "20". Also within the Control element structure tree, locate the TextPrimitive (it should currently read "Text: radPanel1") and set the Alignment property to "MiddleCenter". Close theElement Hierarchy editor dialog. The layout on the form should look something like this screenshot:
398
7. Add three RadButtons below the panel in a horizontal line and set properties:
Name = "btnBack", Text = "Back", Size = "40, 40" Name = "btnInfo", Text = "Info", Size = "40, 40" Name = "btnNext", Text = "Next", Size = "40, 40"
8. For each of the three buttons, open the Smart Tag and select the Edit UI Elements link to bring up the Element Hierarchy Editor. Set the RadButtonElement Shape property to "EllipseShape". The form designer should look something like this screenshot:
9. Select"pnlTitle" in the designer and in the Properties window, open the Databindings property and click the ellipses for the Advanced property. This will bring up the Formatting and Advanced Binding dialog. 10. Configure the bindings for "pnlTitle".
In the tree on the left select the Text property. In the Binding drop down list select Add Project Data Source. Configure theRadPanel to use theMusicCollection Albums table, "AlbumName" column. For more detail, revisit the Data Binding chapter section "Binding to Simple Controls Using DataBindings". The Formatting and Advanced Binding dialog will look something likethe screenshot below.
399
Click OK to close the dialog. The RadPanel DataBindings Text property should look like the screenshot below:
11. Select the form in the designer and again configure the DataBindings.
This time set the BackgroundImage property to the "Image" column of the Albums table. The Formatting and Advanced Binding dialog will look something likethe screenshot below.
400
Click OK to close the dialog. The ShapedForm DataBindings BackgroundImage property should look like the screenshot below:
12. In the designer, double-click the "Back" button and handle the Click event. Earlier when you bound the RadPanel to the Albums table you automatically created an "albumsBindingSource" component that was placed in the component tray below the form designer. Call the BindingSource MovePrevious() method. [VB] Handling the "Back" ButtonClick Event Private Sub btnBack_Click(sender As Object, e As EventArgs) albumsBindingSource.MovePrevious() End Sub [C#] Handling the "Back" ButtonClick Event private void btnBack_Click(object sender, EventArgs e) { albumsBindingSource.MovePrevious(); }
401
That all works pretty well except that the panel and buttons look clunky in this context. We can make these transparent and subtly tinted to fit the color scheme of each image.
402
403
404
405
406
The first step is to set the parent form's IsMdiContainer property to True. Failing to do this will generate an error when you attempt to set the MdiParent of a child form later. The drop down list gets filled with the themes available for a RadForm. Also, we hook up a MdiChildActivate event handler that will sense when a child form is clicked on. [VB] Handling the Form Load Event Private Sub RadForm1_Load(sender As Object, e As EventArgs) Me.IsMdiContainer = True ' disable the delete button - there are no child forms Me.btnDelete.Enabled = False ' load drop down list with theme names Dim themes As ThemeList = ThemeResolutionService.GetAvailableThemes(Me) For Each theme As Theme In themes commandBarDropDownList1.Items.Add(New RadListDataItem(theme.ThemeName)) Next commandBarDropDownList1.SelectedIndex = 0 Me.MdiChildActivate += New EventHandler(RadForm1_MdiChildActivate) End Sub [C#] Handling the Form Load Event
407
408
409
The logic above will work for the most part except that you will need to create a ShapedForm in the "New" button Click event handler and you will need to change references to the title bar, for example: [VB] Accessing the TitleBar ' instead of... child.FormElement.TitleBar ' use... TryCast(child.Controls("radTitleBar1"), RadTitleBar) [C#] Accessing the TitleBar // instead of... child.FormElement.TitleBar; // use... child.Controls["radTitleBar1"] as RadTitleBar;
15.6 Summary
In this chapter you learned how the special RadForm, ShapedForm and RadRibbonForm classes can be inherited from to create themeable, custom shaped forms to complete and polish the look-and-feel of an application. You saw how the new project item templates are used to create instances of each form class. The chapter demonstrated how RadTitleBar is used as a replacement for the built-in Windows form title bar. Finally, the chapter introduced the RadMessage box as a themable replacement for the standard MessageBox.
410
16.1 Objectives
Learn different strategies for organizing form space using RadControls Use RadDock to handle dockable windows and tabbed documents Use RadCarousel to animate a series of clickable images Use RadRotator to display constantly changing personalized content.
16.2 Introduction
For interactive, unique navigation and form "real estate" management, RadDock, RadRotator and RadCarousel let you catch your users attention and make wise use of form space at the same time.
RadDock
RadDock helps you manage multiple windows in your application with a docking system similar to Microsoft Visual Studio 2005.RadDock can contain both tool and tabbed document style windows. RadDock also includes fully interactive design-time layout management.
The RadDock control provides a container that holds dockable windows. This container can fill the entire client area of a Windows Form, or can be limited to any rectangular area youchoose to manage. Tabbed documents can beswitched between, resized, dragged to arrange in various configurations and closed. Tabbed documents are supported by the DocumentWindow control.You can place other controls (either Telerik RadControls or standard Windows Forms controls) within a DocumentWnidow. Tool windowscan be dragged outside their containers ("floating"), dragged to other containers,collapsed against the side oftheRadDock andtransformed to tabbed documents. Tool windows are supported by the ToolWindow control. You can place other controls (either Telerik RadControls or standard Windows Forms controls) within a ToolWindow. The RadDock Advanced Layout Designer gives you fully interactive design-time control over the number, position, and properties of DockWindows within a RadDock. RadDock collects and uses the information about the state of each DockWindow - FloatingSize, FloatingLocation, AutoHideSize, Previous position, AutoHidePostion, etc. dynamically. RadDock offers an access to the active window. There are CloseAction and AutoDispose properties which allow control over the windows Close behavior, as well as over memory management of the SplitPanel and DockWindow objects. Different sizing modes (Auto, Relative, Absolute, Fill) virtually any layout scenario can be easily achieved. The user has complete control over sizing and layout behavior. RadSplitContainer composes a RadSplitContainerLayoutStrategy, which handles any layout request for this container. If the available size modes are not enough to fit into a layout scenario, then the entire layout strategy may be easily replaced/extended with a custom one. RadDock stores all sizing information per panel in a separate object allows for easy transition from one state to another and vice-versa without loosing the sizing information for each state. Load Layout allows for restoring previous scene at 100% - a layout persistency operation should now only serialize/de-serialize the sizing info of each panel in order to completely store/restore its position on a split container. Redock support (transition to previous docked or floating state of Dock Windows) has been completely revisited for the new RadDock implementation. A service-based semantic is introduced, which saves a windows state just before any dock operation is about to occur, and this state can easily be restored later
411
RadRotator
RadRotator is a multi-purpose component for content rotation and personalization. Highly customizable, it delivers high interactivity and user involvement. You can display a series of images, web URLs or any collection of rad elements. For example, if you use RadButtonElement or RadButtonImageElement, the user will be able to clickan item before it rotates out ofview.Animation between frames can be opaque or transparent and the movement can be in any direction. You can adjust the level of granularity and interval between frames.
412
RadCarousel
RadCarousel animates a series of elements either by the user clicking a particular element or by clicking the forward and back arrows. Thecarousel elements appear to animate through a "path", i.e. a route in three dimensions. The path can beelliptical or along aBezier curve. RadCarousel supports databinding, smooth animations and transitions, automatic generation of image reflections and dynamic addition and removal of items.
413
414
RadDock Setup
1. From the Toolbox, add a RadDock to the form. Set the Dock property to "Fill"and ThemeName to Office2007Silver. 2. In the RadDock Smart Tag click the Show Advanced Layout Designer... link. Using the options in the ribbon, configure the layout:
Click the ToolWindow | Left menu item. Click the ToolWindow | Bottom menu item.
415
Click the Add Document Windowmenu item. Drag toolWindow2 under toolWindow1. When the designer looks like this screenshot below, click the Save and Close button.
3. Click the client area (not the title bar) for "toolWindow1" to select it. In the Properties window change the Text property to "RadCarousel". 4. Click the client areafor "toolWindow2" to select it. In the Properties window change the Text property to "RadRotator". 5. Increase the size of the split container so the toolwindows to take approximately half of the form size. 6. Press Ctrl-F5 to run the application so far.
416
Experiment with the docking features. Verify that you can drag and float a window, that the window will re-dock either as a panel or in the tabbed documents area. Check that the auto-hidden (un-pinned) panel can be expanded and pinned. Use the splitter bars to resize the relative areas. 7. Add a RadRotator to the "RadRotator" panel and set its Dock property to "Fill". 8. Click the ellipses for the Items property to display the RadItem Collection Editor. Using the Add button drop down list, add 3 RadButtonElements. 9. Drag a RadCarousel control to the dock panel and set its Dock property to "Fill". 10. Click the ellipses for the Items property to display the RadItem Collection Editor. Using the Add button drop down list, add 3 RadButtonElements . 11. Add six images as project resourses, which we will use for the button elements. 12. In the form Load event, set the Image, DisplayStyle and ImageAlignment properties for all six button elemens. Then set the EnableAutoLoop property of RadCarousel to true and the Running property of RadRotator to true. [VB] Configure images and start rotating and looping for RadRotator and RadCarousel Private Sub RadForm1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Me.RadButtonElement1.Image = New Bitmap(My.Resources.Lighthouse, New Size(200, 200)) Me.RadButtonElement1.DisplayStyle = Telerik.WinControls.DisplayStyle.Image Me.RadButtonElement1.ImageAlignment = System.Drawing.ContentAlignment.MiddleCenter Me.RadButtonElement2.Image = New Bitmap(My.Resources.Penguins, New Size(200, 200)) Me.RadButtonElement2.DisplayStyle = Telerik.WinControls.DisplayStyle.Image Me.RadButtonElement2.ImageAlignment = System.Drawing.ContentAlignment.MiddleCenter Me.RadButtonElement3.Image = New Bitmap(My.Resources.Tulips, New Size(200, 200)) Me.RadButtonElement3.DisplayStyle = Telerik.WinControls.DisplayStyle.Image Me.RadButtonElement3.ImageAlignment = System.Drawing.ContentAlignment.MiddleCenter
417
418
Dock New Window To Left/Top/Right/Bottom: Adds tool windows to their respective positions within RadDock. Add Tabbed Document: Adds DocumentWindows to RadDock. Show Advanced Layout Designer: This designer lets you work with tool windows and documents windows with drag-and-drop ease similar to the runtime behavior, then save the results back to the design environment.
To add tool windows to the layout, select one of the predifined buttons in the Tool Windows pane. To add DocumentWindow click "Add Document Window" button. You drag-and-drop tool and document windows, just as you can at run time. When you are satisfied with your layout, click the Save and Close button to close the Advanced Layout Designer and apply the layout to RadDock control on your form. To abandon your changes click the window "x" close button in the upper right hand corner of the form ot click gthe"Discard and Close" button.
419
After the rotator is populated, you can navigate through the elements right in the designer using the next and back buttons. Set the Running property true to have the items animate at design time.
420
RadCarousel
The RadCarousel Smart Tag has a Edit Items link to access the Items collection. The other key design-time aspect is the CarouselPath. In the CarouselPath property you can choose between a Bezier or elliptical path.
By default CarouselPath is a CarouselEllipsePath. Drag the Center point grip to move the entire carousel control around the form during design-time. Drag the two control points U and V to alter the tilt and dimensions of the ellipse.
421
If you choose CarouselBezierPath, you get a FirstPoint, LastPoint and two control points "CtrlPoint1" and "CtrlPoint2". You can drag all four points in the designer to define the curve.
You can arrange the points only in 2D. Z coordinates must be set programmatically if needed. Also note that you can drag the control points over the whole designer area, i.e. you are not limited to the form only.
422
423
Once you have the RadDock populated, you can retrieve the collection of DockWindow instances by accessing the DockWindows property of the control. This property returns a DockWindowCollection with all dockables, even those that are un-pinned orhiddden. [VB] Finding specified window Dim window As DockWindow = Nothing For Each currentWindow As DockWindow In radDock1.DockWindows If currentWindow.Text.Equals("My Window Name") Then window = currentWindow Exit For End If Next [C#] Finding specified window DockWindow window = null; foreach (DockWindow currentWindow in radDock1.DockWindows) { if (currentWindow.Text.Equals("My Window Name")) {
424
Close -When a DockWindow has its CloseAction set to Close, this window is closed and detached (but not disposed) from its RadDock. You cannot manage it from RadDock collections anymore. Hide - When a DockWindow has its CloseAction set to Hide, this window is only closed (hidden) in RadDock. However, this window is not detached from its RadDock and you can manage it from the RadDock collections. CloseAndDispose -When a DockWindow has its CloseAction set to CloseAndDispose, this window is closed and then disposed.
RemoveWindow This method closes and detaches (but does not dispose) a DockWindow regardless of its CloseAction property. This will happen if you pass only a DockWindow as a parameter. In addition, you can pass a CloseAction parameter in the RemoveWindow method. In this case, the RemoveWindow method will act differently in accordance with this parameter.
425
RadDock Properties
ActiveWindow: Sets or gets the currently active DockWindow (ToolWindow or DocumentWindow). AutoDetectMdiChildren: Allows RadDock to automatically control MDI child windows of a parent form. DockWindows: A collection of IDockWindow objects being managed by the RadDock. DockWindows.ToolWindows: A collection of the ToolWindows being managed by the RadDock. DockWindows.DocumentWindows: Gets a collection of the DocumentWindows being managed by the RadDock. FloatingWindows: Gets a collections of the floating windows. Dock: This property is not specific to RadDock, but rather is a general Controls property that indicates what are of a parent control will be occupied. This DockStyle enumeration can be Fill, Top, Bottom, Left, Right and None. MdiChildren: An array of MDI forms parented in the RadDock. This array is accessible at runtime. MainDocumentContainerVisible: Indicates whether main document container will be initially visible. QuickNavigatorSettings: this property give you an object of type QuickNavigatorSettings. This object gives you a full control over the Quick Navigator features.
RadDock Methods
ActivateWindow(DockWindow window): Activates a DockWindow. AddDocument(DockWindow window): Adds a DockWindow as a DocumentWindow in RadDock. AutoHideWindow(DockWindow window): Makes the specified DockWindow auto-hidden. AutoHideWindows(IEnumerable<DockWindow> windows, AutoHidePosition position): Makes the specified DockWindow collection auto-hidden. CloseAllWindows(): Closes all DockWindows. The CloseAction property specifies whether a ToolWindow/DocumentWindow will be Closed, ClosedAndDisposed or just Hidden. CloseWindow(DockWindow window): Closes a specified ToolWindow or DocumentWindow. DockWindow(DockWindow window, DockPosition position): Docks a DockWindow (ToolWindow/DocumentWindow) at the specified position. DockWindow(DockWindow window, DockWindow target, DockPosition position): Docks a DockWindow at a position relative to the specified target DockWindow. FloatToolTabStrip(ToolTabStrip strip, Rectangle bounds): Floats a ToolTabStrip with ToolWindows in a
426
FloatWindow(DockWindow window): Floats the specified DockWindow in a new form. FloatWindow(DockWindow window, Rectangle bounds): Floats the specified DockWindow in a new form. The form has bounds specified by the bounds parameter. LoadFromXml(fileName): Deserializes RadDock layout structure. SaveToXml(fileName): Serializes the RadDock layout structure. This method does not save content. See Loading and Saving Layouts for more information. RemoveWindow(DockWindow window): Removes a ToolWindow or DocumentWindow from the list of managed dockables.
DockWindows
Each DockWindow instance has information about its own state, position, etc. Here are some especially useful properties.
DockState: Floating, Docked, TabbedDocument, AutoHide (un-pinned), Hidden. DockType: ToolWindow (i.e. a DockPanel), Document. Image: displayed in the window title bar. Text: displayed in the window title bar.
[VB] IDockable Methods If radDock1.ActiveWindow IsNot Nothing Then Dim builder As New StringBuilder() builder.Append("DockState: " & radDock1.ActiveWindow.DockState.ToString()) builder.Append(Environment.NewLine) builder.Append("DockType: " & radDock1.ActiveWindow.DockType.ToString()) builder.Append(Environment.NewLine) builder.Append("Text: " + radDock1.ActiveWindow.Text) RadMessageBox.Show(builder.ToString(), "DockWindow Properties") End If [C#] IDockable Methods if (radDock1.ActiveWindow != null) { StringBuilder builder = new StringBuilder(); builder.Append("DockState: " + radDock1.ActiveWindow.DockState.ToString()); builder.Append(Environment.NewLine); builder.Append("DockType: " + radDock1.ActiveWindow.DockType.ToString()); builder.Append(Environment.NewLine); builder.Append("Text: " + radDock1.ActiveWindow.Text); RadMessageBox.Show(builder.ToString(), "DockWindow Properties"); }
427
RadDock also has a ActivateWindow() method that puts focus on the specified window. The example below iterates the managed dockable windows and if it finds one with the text "Products", activates that window. [VB] Activating DockWindow Dim foundDockable As DockWindow = Nothing For Each dockable As DockWindow In radDock1.DockWindows If dockable.Text.Equals("Products") Then foundDockable = dockable Exit For End If Next If foundDockable IsNot Nothing Then radDock1.ActivateWindow(foundDockable) End If [C#] Activating DockWindow DockWindow foundDockable = null; foreach (DockWindow dockable in radDock1.DockWindows) { if (dockable.Text.Equals("Products")) { foundDockable = dockable; break; }
428
429
You can find the complete source for this project at: \RealEstate\<VB|CS>\DockUserControl
430
431
[VB] Hosting MDI Child Forms Private Sub MDIParent_Load(sender As Object, e As EventArgs) Me.IsMdiContainer = True radDock1.AutoDetectMdiChildForms = True End Sub Private Sub btnAddChildForm_Click(sender As Object, e As EventArgs) Dim childForm As New RadForm() childForm.MdiParent = Me childForm.Text = "New Child Form - " + DateTime.Now.ToString() childForm.Show() End Sub [C#] Hosting MDI Child Forms private void MDIParent_Load(object sender, EventArgs e) { this.IsMdiContainer = true; radDock1.AutoDetectMdiChildForms = true; } private void btnAddChildForm_Click(object sender, EventArgs e) { RadForm childForm = new RadForm(); childForm.MdiParent = this; childForm.Text = "New Child Form - " + DateTime.Now.ToString(); childForm.Show(); } Call ActivateMdiChild() to select a given child form: [VB] Activating an MDI Child Form in the DockingManager radDock1.ActivateMdiChild(childForm) [C#] Activating an MDI Child Form in the DockingManager radDock1.ActivateMdiChild(childForm);
432
You can find the complete source for this project at: \RealEstate\<VB|CS>\ProgrammingDock [VB] Loading and Saving Layout Private Sub btnLoad_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnLoad.Click Dim dialog As New OpenFileDialog() dialog.DefaultExt = "xml" If dialog.ShowDialog() = DialogResult.OK Then RadDock1.LoadFromXml(dialog.FileName) lblStatus.Text = "Loaded layout " + dialog.FileName End If End Sub Private Sub btnSave_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSave.Click Dim dialog As New SaveFileDialog() dialog.DefaultExt = "xml" If dialog.ShowDialog() = DialogResult.OK Then RadDock1.SaveToXml(dialog.FileName)
433
RadRotator
The first task working with RadRotator is to load the Items collection with any RadElement. You can alsoadd aRadHostItem that wraps some other standard Windows Forms control. After the items are loaded, call the RadRotator Start() method to begin animating between items and Stop() to end animation. You could instead set the Running property to True to begin animating. When the Running property is set to true or the Start() method is called, the StartRotation event fires. Using the arguments passed to StartRotation you can cancel animation before it begins. When the animation is ended, the StopRotation event is fired. While the StartRotation and StopRotation event bracket the entireanimation, BeginRotate and EndRotate events are fired just before and after a transition between rotator items. BeginRotate passes a
434
The LoadRotator()creates one of the RadElement types, set the Text, Image and other properties of the element and finally add the element to the RadRotator Items collection. In the form Load event handler we're setting the AnimationFrames to be 30 instead of the default 10 to make the animation smoother. We're setting the Interval to "3000" or three seconds. The LocationAnimation is set to -1, -1 so that the images animate down from the upper left to lower right.
435
436
RadCarousel
RadCarousel is similar to the RadRotator in that the first job is to fill the Items collection with RadElements. This can be done at design time, programmatically and through data binding. Here's a simple example of adding some RadButtonElements.
437
[VB] Adding Elements to the RadCarousel Items Collection Dim btnProducts As New RadButtonElement("Products") btnProducts.MinSize = New Size(75, 50) radCarousel1.Items.Add(btnProducts) Dim btnServices As New RadButtonElement("Services") btnServices.MinSize = New Size(75, 50) radCarousel1.Items.Add(btnServices) Dim btnTraining As New RadButtonElement("Training") btnTraining.MinSize = New Size(75, 50) radCarousel1.Items.Add(btnTraining) [C#] Adding Elements to the RadCarousel Items Collection RadButtonElement btnProducts = new RadButtonElement("Products"); btnProducts.MinSize = new Size(75, 50); radCarousel1.Items.Add(btnProducts); RadButtonElement btnServices = new RadButtonElement("Services"); btnServices.MinSize = new Size(75, 50); radCarousel1.Items.Add(btnServices); RadButtonElement btnTraining = new RadButtonElement("Training"); btnTraining.MinSize = new Size(75, 50); radCarousel1.Items.Add(btnTraining);
438
Simply create an instance of RadWebBrowserElement, setits size and Url and add it to the Items collection of RadCarousel. [VB] Creating RadButtonElement with Web Browser Image Dim webBrowser1 As New RadWebBrowserElement() webBrowser1.MinSize = New System.Drawing.Size(200, 200) webBrowser1.WebBrowserItem.Url = New Uri("http://www.telerik.com") radCarousel1.Items.Add(webBrowser1) Dim webBrowser2 As New RadWebBrowserElement() webBrowser2.MinSize = New System.Drawing.Size(200, 200) webBrowser2.WebBrowserItem.Url = New Uri("http://www.telerik.com/products/winforms.aspx") radCarousel1.Items.Add(webBrowser2) Dim webBrowser3 As New RadWebBrowserElement() webBrowser3.MinSize = New System.Drawing.Size(200, 200) webBrowser3.WebBrowserItem.Url = New Uri("http://tv.telerik.com/") radCarousel1.Items.Add(webBrowser3) [C#] Creating RadButtonElement with Web Browser Image RadWebBrowserElement webBrowser1 = new RadWebBrowserElement(); webBrowser1.MinSize = new System.Drawing.Size(200, 200); webBrowser1.WebBrowserItem.Url = new Uri("http://www.telerik.com
439
DataBinding
You can find the complete source for this project at: \<VB|CS>\RealEstate\RadCarouselProgramming Databinding takes an additional step compared to other RadControls that need a simple, one-column, set of data. You will need to handle the NewCarouselItemCreating event to add elements you want available later when the ItemDataBound event fires. In the form Load event you can hook up your DataSource. In this example we use an RSS (Really Simple Syndication) URL to retrieve an XML filewith columns for "title" and "link". The XmlTextReader object from the System.Xml namespace will read directly from an RSS URL.You can feed this reader to a DataSet using its ReadXml() method. Now you have a populated DataSet that can be assigned directly to the RadCarousel DataSource property except that we don't want to display every last record. Extract just a few rows into a generic List of DataRow and assign that list instead. [VB] Assigning the DataSource Private Sub RadForm1_Load(sender As Object, e As EventArgs) radCarousel1.VisibleItemCount = 5 Dim reader As New XmlTextReader("http://silverlight.net/blogs/MainFeed.aspx") Dim ds As New DataSet() ds.ReadXml(reader) ' get just the top three links Dim topRows As New List(Of DataRow)() Dim i As Integer = 0 While i < radCarousel1.VisibleItemCount topRows.Add(ds.Tables("item").Rows(i)) System.Math.Max(System.Threading.Interlocked.Increment(i),i - 1) End While radCarousel1.DataSource = topRows End Sub [C#] Assigning the DataSource private void RadForm1_Load(object sender, EventArgs e) { radCarousel1.VisibleItemCount = 5; XmlTextReader reader = new XmlTextReader("http://silverlight.net/blogs/MainFeed.aspx"); DataSet ds = new DataSet(); ds.ReadXml(reader); // get just the top three links List<DataRow> topRows = new List<DataRow>(); for (int i = 0; i < radCarousel1.VisibleItemCount; i++) {
440
441
442
443
Item Interaction
ItemClickDefaultAction controls if the carousel animates when the user clicks an item. When set to SelectItem, clicking on a carousel item causes the item carousel to animate. When set to None, the items remain static in the carousel. ItemReflectionPercentage is the percentage amount of reflection displayed, relative to the size of the item. SelectedIndex is similar to the same property in a list box by indicating the ordinal position of the currently selected item.
16.6 Summary
In this chapter you learned some stylish and unique ways of organizing form space using RadDock to handle dockable windows and tabbed documents, RadCarousel to animate a series of clickable images and RadRotator to display constantly changing personalized content.
444
17.1 Objectives
Become familiar with RadCalendar extensive customization features. Work withselected days. Work with the "Special Days" collection to mark specific days or repeating events.
17.2 Introduction
RadCalendar is a lightweight yet highly advanced date input control for Windows Forms. Zoom, select multiple dates, view several months at once, use it as a date picker, or even add a Hebrew calendar to your forms.
Just about everything on the calendar can be customized to suit your purposes.
Title displays the selected date range and navigation buttons. The appearance of both title and the navigation buttons can be customized. Navigation Buttons allow you to move to the previous/next month or jump X number of months at a time. The Main Calendar Area rendersa single or multiple month "calendar view". This area includes all of the individual days and the row & column selectors. Row and Column Headers let your user select a whole row or column of dates at a time by clicking on the respective day or week button. Use the View Selector button to select all cells in the current month. If multiple months are being displayed at one time, there will be one view selector per month. The StatusBar footer area below the Main Calendar Area can be used for visual customization or for displaying additional information about the selected item. When the user clicks the Title, theFast Navigation Popup displays a window with the months and years surrounding the selected date (not visible on the screenshot)
445
446
Anchor = "Top, Bottom, Left Right" ShowRowHeader = True ShowViewSelector = True AllowMultipleSelect = True AllowColumnHeaderSelectors = True AllowRowHeaderSelectors = True AllowViewSelector = True ShowFooter = True Add a RadButton below the calendar, name it "btnGetFlights" and set the Text to "Get Flights".
2. Double-click the button to create a Click event handler. Add the code below that iterates the SelectedDates collection of DateTime objects and builds a string to display in a RadMessageBox. [VB] Handling the Click Event Private Sub btnGetFlights_Click(sender As Object, e As EventArgs) Dim builder As New StringBuilder() For Each dateTime As DateTime In radCalendar1.SelectedDates builder.Append(dateTime.ToLongDateString()) builder.Append(Environment.NewLine) Next RadMessageBox.SetThemeName("Aqua") RadMessageBox.Show(builder.ToString(), "Look for flights on these days?", MessageBoxButtons.YesNo, RadMessageIcon.Question) End Sub [C#] Handling the Click Event private void btnGetFlights_Click(object sender, EventArgs e) { StringBuilder builder = new StringBuilder(); foreach (DateTime dateTime in radCalendar1.SelectedDates) { builder.Append(dateTime.ToLongDateString()); builder.Append(Environment.NewLine); } RadMessageBox.SetThemeName("Aqua"); RadMessageBox.Show(builder.ToString(), "Look for flights on these days?", MessageBoxButtons.YesNo, RadMessageIcon.Question); } 3. Run the application and verify that you can select multiple days,that you canselect the entire month usingthe view selector and that you can select rows and columns using the corresponding selectors. Try selecting the dates in a random order. Notice that the DateTime objects in SelectedDates are in the order they were selected.
447
Image, Text and ToolTip properties of navigation buttons found to the left and right of the title can be found in the Navigation Management group of properties.
Toggle the ability to use the navigation and fast navigation using the Navigation properties AllowNavigation and AllowFastNavigation.
In a separategroup of properties called Header Settings,youcontrol if the navigation buttons are even shown using ShowFastnavigationButtons and ShowFastnavigationButtons.
By default the navigation buttons move you forward and back one month at a time and the fast navigation buttons move you 3 months at a time. The FastNavigationStep step is the number of months that the fast navigation buttons move you at a time.
448
To allow an entire row, column or all day cells for the view to be selected at one time, toggle the AllowRowHeaderSelectors, AllowColumnHeaderSelectors and AllowViewSelector behavior properties. If you want to set AllowRowHeaderSelectors, AllowColumnHeaderSelectors and AllowViewSelector to True, you must also set AllowMultipleSelect to be True.
Footer
The footer is located below the month day cells and is visible if the ShowFooter property is True. The footer shows a date and time that automatically updates, a Clear button that clears all selections in the current view and a Today button that selects the current date. Access footer buttons through the ClearButton and TodayButton objects, e.g. ClearButton.Text.
FocusedDate
The FocusedDate property determines the current view. For example, if you want to show the month of January 2000 when you first display the calendar, then set theFocusedDate to 1/1/2000.
449
Orientation
Orientation by default is Horizontal, with the days progressing from left to right or right to left (see Globalization for more information). Orientation can also be Vertical to list the days from top to bottom or bottom to top.
Month Layout
Columns and rows and be displayed in a number of MonthLayout configurations.
450
[VB] Comparing the SelectedDate and SelectedDates Properties Dim builder As New StringBuilder() builder.Append("Selected Date: ") builder.Append(radCalendar1.SelectedDate.ToLongDateString())
451
You can find the complete source for this project at: \<VB|CS>\Programming
452
You can passa DateTime to the RadCalendarDay in one of the constructor overloads to automatically assign the Date.The FocusedDate property assignment moves focus to the month of January. [VB] Adding a Special Day ' assign New Years as a special day Dim day As New RadCalendarDay(New DateTime(2010, 1, 1)) radCalendar1.SpecialDays.Add(day) radCalendar1.SpecialDays(0).Image = imageList1.Images("blackout.ico") radCalendar1.FocusedDate = day.[Date] [C#] Adding a Special Day // assign New Years as a special day RadCalendarDay day = new RadCalendarDay(new DateTime(2010, 1, 1)); radCalendar1.SpecialDays.Add(day); radCalendar1.SpecialDays[0].Image = imageList1.Images["blackout.ico"]; radCalendar1.FocusedDate = day.Date;
Templates
Assign a RadHostItem to the ItemTemplate if you want to include any Controls including standard Windows forms controls and RadControls. The example below creates a special day for New Years Eve day and assigns a standard CheckBox to the RadHostItem, then assigns the RadHostItem to the ItemTemplate property.
453
Recurring Days
A RadCalendarDay object can be configured as a repeating event. Set the Recurring property to:
DayInMonth: Only the day part of the date is taken into account. The event repeats every month on the same day. DayAndMonth: The month and the day part of the date are taken into account. The event repeats in a specific month on the same day. Week: The week day is taken into account. The event repeatson a specific day of the week. WeekAndMonth: The week day and the month are taken into account. The event repeats in a specific week day in a specific month. Today: Gives the ability to control the visual appearance of today's day. None: Default value - means that the day in question is a single point event, no recurrence.
[VB] Adding Recurring Dates Dim fridays As New RadCalendarDay(New DateTime(2010, 1, 8)) fridays.Recurring = RecurringEvents.Week radCalendar1.SpecialDays.Add(fridays) [C#] Adding Recurring Dates RadCalendarDay fridays = new RadCalendarDay(new DateTime(2010, 1, 8)); fridays.Recurring = RecurringEvents.Week; radCalendar1.SpecialDays.Add(fridays); You can find the complete source for this project at:
454
Calendar Events
ElementRender
You can dial-in the appearance of each individual calendar cell element using the ElementRender event. ElementRender is fired after the generation of every calendar cell object and just before it gets rendered. It is the last place where changes to the already constructed calendar cells can be made. ElementRender argumentsinclude a Day(RadCalendarDay) and a visual Element that is about to be rendered. The example below determines if the Day is from the SpecialDays collection, then uses the properties of Element to paint a glossy gradient on the background, makes the ForeColor transparent (to hide the day number) and adds a tooltip.
[VB] Handling the ElementRender Event Private Sub radCalendar1_ElementRender(sender As Object, e As RenderElementEventArgs) Dim isSpecialDay As Boolean = radCalendar1.SpecialDays.Find(e.Day.[Date]).Length > 0 If isSpecialDay Then e.Element.BackColor = Color.FromArgb(105, 181, 218) e.Element.BackColor2 = Color.FromArgb(112, 145, 181) e.Element.BackColor3 = Color.Blue e.Element.NumberOfColors = 3 e.Element.GradientStyle = GradientStyles.OfficeGlassRect e.Element.GradientPercentage = 80 e.Element.ForeColor = Color.Transparent e.Element.ToolTipText = "Blackout date" End If End Sub [C#] Handling the ElementRender Event private void radCalendar1_ElementRender(object sender, RenderElementEventArgs e) { bool isSpecialDay = radCalendar1.SpecialDays.Find(e.Day.Date).Length > 0; if (isSpecialDay) { e.Element.BackColor = Color.FromArgb(105, 181, 218); e.Element.BackColor2 = Color.FromArgb(112, 145, 181); e.Element.BackColor3 = Color.Blue; e.Element.NumberOfColors = 3; e.Element.GradientStyle = GradientStyles.OfficeGlassRect; e.Element.GradientPercentage = 80; e.Element.ForeColor = Color.Transparent;
455
456
Visual Customization
Most aspects of the calendar UI are surfaced directly through properties. For example, the footer Clear and Today buttons can be changed at design time or in code simply by using the corresponding properties TodayButton and ClearButton:
[VB] Setting Footer Button Properties radCalendar1.TodayButton.Text = " Go to Today " radCalendar1.ClearButton.Text = " Erase " [C#] Setting Footer Button Properties radCalendar1.TodayButton.Text = " Go to Today "; radCalendar1.ClearButton.Text = " Erase "; What if you want to replace the footer with some custom information or elements? We can shut off both buttons and the updating clock information on the left of the footer and add a custom element in its place. Here we set the Visibility property of all three elements to Collapsed so they don't take up any space, then add a new RadButtonElement that expands to fill the entire footer.
[VB] Adding a Custom Element Private Sub Form1_Load(sender As Object, e As System.EventArgs) radCalendar1.ShowFooter = True radCalendar1.ClearButton.Visibility = ElementVisibility.Collapsed radCalendar1.TodayButton.Visibility = ElementVisibility.Collapsed ' get the footer layout panel Dim layoutPanel As DockLayoutPanel = TryCast(radCalendar1.CalendarElement.Children (0).Children(0).Children(0), DockLayoutPanel) ' get the updating date and time label and hide that too layoutPanel.Children(2).Visibility = ElementVisibility.Collapsed ' create a new custom element and add it Dim button As New RadButtonElement()
457
[VB] Adding a Rotator Element to the Footer Private Sub Form1_Load(sender As Object, e As System.EventArgs) radCalendar1.ShowFooter = True radCalendar1.ClearButton.Visibility = ElementVisibility.Collapsed radCalendar1.TodayButton.Visibility = ElementVisibility.Collapsed ' get the footer layout panel Dim layoutPanel As DockLayoutPanel = TryCast(radCalendar1.CalendarElement.Children
458
Globalization
RadCalendar provides built in internationalization support to build world-ready applications. RadCalendar supports the System.Globalization namespace. System.Globalization consists of classes (CompareInfo, CultureInfo, RegionInfo, etc.) that contain culture-related information, such as the language, country/region, calendars in use, format patterns for dates, currency, and numbers, and the sort order for strings.
459
You can find the complete source for this project at: \Calendar\<VB|CS>\Globalization Setting the Culture property automatically re-labels in the language and format of the culture. Culture is a System.Globalization namespace CultureInfo object that can be set to known culture codes. In the screenshot above the calendar is set to Bengali, a culture code of "bn-BD". You can do the same by creating a new CultureInfo object and passing any available culture code in the constructor or use the static CultureInfo.GetCultureInfo() to return a CultureInfo. [VB] Assigning the Culture radCalendar1.Culture = New CultureInfo("bn-BD") [C#] Assigning the Culture radCalendar1.Culture = new CultureInfo("bn-BD"); For languages that run right-to-left, simply assign the calendar RightToLeft property a value of Yes, No, or Inherit (inherits the direction of the parent control). [VB] Assigning the RightToLeft Property radCalendar1.RightToLeft = If(cbRightToLeft.Checked, RightToLeft.Yes, RightToLeft.No) [C#] Assigning the RightToLeft Property radCalendar1.RightToLeft = cbRightToLeft.Checked ? RightToLeft.Yes : RightToLeft.No;
460
Assign a FirstDayOfWeek enumeration member a value of Monday..Sunday or Defaultto be handled by the System.Globalization.Calendar object. [VB] Assigning the FirstDayOfWeek radCalendar1.FirstDayOfWeek = FirstDayOfWeek.Monday [C#] Assigning the FirstDayOfWeek radCalendar1.FirstDayOfWeek = FirstDayOfWeek.Monday; The format for the day column headings is handled by the DayNameFormat property and corresponding enumeration: [VB] Assigning the DayNameFormat radCalendar1.DayNameFormat = DayNameFormat.[Short] [C#] Assigning the DayNameFormat radCalendar1.DayNameFormat = DayNameFormat.Short;
The other "format" properties that relate to globalization take formatting strings:
TitleFormat: The default value is "MMMM yyyy" shows the full month and year. DayCellFormat: The default value is "%d" prints the simple integer day of the month number in each cell. CellToolTipFormat: The default value is "dddd.MMMM dd, yyyy".
One other miscellaneous property is the DateRangeSeparator that appears between start and end months in a multi-view title. Thie property defaults to " - ". For an overview on globalization in general, see the MSDN article "Introduction to International
461
17.6 Summary
This chapter focused on using the extensive customization features of RadCalendar to completely tailor the calendar header, calendar footer, number of displayed months, the number of rows and columns, date ranges, selected and focused dates, the first day of the week as well as the title and navigation areas of the calendar. You learned how to work with the selected days in the calendar. The chapter also explained how to work with the "special days" collection to mark specific days or repeating events.
462
18.1 Objectives
Learn how to create shortcuts and global shortcuts Learn how to create shortcuts for RadControls Learn how to create shortcuts for menu items Explore theRadShortcut functionality
18.2 Introduction
Almost each application uses the so called Shortcuts a keyboard combination that triggers a specific action. For a valid shortcut is considered any keyboard combination where a Modifier Key (CTRL, ALT and SHIFT or a combination of these) is down and other key(s) is pressed. This semantic is available out-of-the-box in our framework and allows you to seamlessly plug any valid keys combination as an action accelerator. Supported are also the so called multi-keys shortcuts where the Keys member of each shortcut may be more than one key e.g. Ctrl + A, S is recognized by the framework. Shortcuts without modifier keys are also supported, but they should be used with caution, since they may be in conflict with other controls which intercept keyboard input. The following diagram illustrates the object model and class hierarchy that lie behind each RadShortcut:
The entire mechanism is controlled by several interfaces and classes which provide very easy and intuitive way to register different shortcuts.
RadKeyboardFilter: This class listens to all keyboard messages that come on the applications message queue and delegates them to each IKeyboardListener registered. RadShortcutManager: A concrete implementation of IKeyboardListener interface which is plugged into the RadKeyboardFilter instance. Stores a collection of IShortcutProvider instances, recognizes a valid shortcut combination, provided by any of the registered IShortcutProvider and calls the IShortcutProvider.OnShortcut(RadShortcut) callback of the matched provider. RadItem.Shortcuts: Each RadItem implements the IShortcutProvider interface and allows number of shortcuts to be associated with it. When a keyboard combination matches any of the items shortcuts, the
463
4. Click and the newly created item to open the dropdown menu and create a submenu item. By default, the text of the new item will be set to radMenuItem2. Change it to File from the Properties Window:
5. Double click both menu items to create their Click event handlers. 6. In both event handlers add code to show a message box when the item is clicked: [VB.NET] Handle RadMenuItem click event Private Sub RadMenuItem1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles RadMenuItem1.Click RadMessageBox.Show("New") End Sub Private Sub RadMenuItem2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles RadMenuItem2.Click RadMessageBox.Show("File") End Sub [C#] Handle RadMenuItem click event private void radMenuItem1_Click(object sender, EventArgs e) { RadMessageBox.Show("New");
464
465
466
467
468
469
19.1 Objectives
Learn how to bind data to the scheduler. Learn how to add, remove and iterate appointments. Learn how to work with resources. Learn how to modify the view (i.e. week, day, month) and manipulate appointment status. Learn how to drag and drop appointments into the scheduler.
19.2 Introduction
RadScheduler is a highly-customizable appointment presentation component that offers rich Outlook-style functionality. The product delivers swift performance, simplified deployment and limitless customization capabilities and is suitable for use in large-scale enterprise applications. The structure of the RadScheduler control varies slightly, depending on the View. The RadScheduler structure below has the same elements for day and week type views.
In the left border of the scheduler is the Ruler area. The current time is marked within the ruler by the Current Time Thumb. The top of the scheduler is the Header and displays dates that appointments can be created in. Below the Headerare the All Day Appointments that have no specific duration in hours. Underneath the All Day Appointments is the Appointment Area that contains any number of Appointments.
In addition, Navigation Elements let the user jump forward or backwards to the nearest appointment.
470
The month view of the schedulersimply has a Header, Month Cells for every day in the month andzero or more Appointment Cellsin each month cell.
Recurrence Appointments canrecurdaily, weekly, monthly and yearly. The user can set the interval using the "Recurrence" button in the "Edit Appointment" dialog. Here they can set the appointment duration, the frequency appointments should occur and the range that occurrences should fall within. These settings can also be configured programmatically.
471
Appointments can be configured programmatically to recur every minute or hour. Binding Data RadScheduler's DataSource property lets you bind to objects that inherit the base abstract SchedulerDataSource class. The SchedulerBindingDataSource implementation of SchedulerdataSource binds traditional data stores like lists of business objects and database tables. You can find the SchedulerBindingDataSource component in the Toolbox. To have the data source make any sense to the SchedulerBindingDataSource you also need to definemappings that link the expected information to columns in a database table or business object. There are two mapping objects that need to be loaded up and assigned, the AppointmentMappingInfo and ResourceMappingInfo. AppointmentMappingInfo has a series of string properties that point to all appointment related data such as start date/time, end date/time, a description, etc. The ResourcesMappingInfo object has a Name and Image. Here's a dataset design view for the SchedulerData.mdf database file that ships with RadControls for Winforms. You can see all the fields that can be defined forappointments and resources. Also noticea "join table" named"TransientAppointmentsResources" thatassigns a particular resourceto an appointment. Notice that while the database structure allows for multiple resources, the built-in scheduler dialog only allows a single resource to be selected at a time.
472
The foreign key relationship between "TransientAppointmentsResources" and the "Appointments" table will also be definedin theAppointmentMappingInfo object.
You can find SchedulerData.mdb (Access) and SchedulerData.mdf (MS SQL database file)in the installation directory under \Examples\QuickStart\DataSources. Here's some example code that demonstrates loading the AppointmentMappingInfo fields with column names in a database table. The Resources property is assigned the name of the foreign key that joins the Appointments and the "join table' that sits between the appointments and resources table. The ResourceID property is assigned to the column in the "join table" of a unique resource identifier. RadScheduler works from a provider model so thatin the future, custom appointment and resource providers
473
474
475
476
3. In the "Choose a Data Source Type" page of the wizard, select the Database type and click the Next button to continue. 4. In the "Choose a Data Connection" page of the wizard, add a connection to the SchedulerData.mdf file supplied with RadControls for WinForms distribution.
Click the New Connection... button to display the Add Connection dialog. Click the Change button and select the Access Database File option. Set the Database File Name to the Schedulerdata.mdb file located in the RadControls for Winforms installation directory under \Examples\QuickStart\DataSources. Click OK to close the Add Connecction dialog.
5. Back in the "Choose a Data Connection" page of the wizard, click the Next button to continue. 6. A dialog will popup to ask where the file should be located. Choose No to leave the file located in the \Examples\QuickStart\DataSources directory. 7. In the "Save the Connection String in the Application Configuration File" click the Next button to continue. 8. In the "Choose Your Database Objects" page of the wizard, select the "Tables" checkbox to automatically select the Appointments, Resources and AppointmentsResources tables. 9. Click Finish to complete the wizard and close the dialog. This step will create a DataSet component and add it to the component tray below the form designer.
10. Click the "SchedulerDataDataSet" Smart Tag and select Edit in Dataset Designer. Add a relation between the Appointments and AppointmentsResources tables and name it "Appointments_AppointmentsResources". Make the "Key Columns" entry be "ID" from the Appointments tableand set "Foreign Key Columns" from the AppointmentsResources tableto "AppointmentID".
477
11. Build the project. This step will create several useful adapter components we can use to fill the dataset.
12. From these new components, add the AppointmentsTableAdapter 13. Add the code below for the form's Load event handler to fillthe table in the dataset. [VB] Filling the DataSet appointmentsTableAdapter1.Fill(schedulerDataDataSet.Appointments) resourcesTableAdapter1.Fill(schedulerDataDataSet.Resources) appointmentsResourcesTableAdapter1.Fill(schedulerDataDataSet.AppointmentsResources) [C#] Filling the DataSet appointmentsTableAdapter1.Fill(schedulerDataDataSet.Appointments);
478
479
The active view cannot be changed if the new view is not in the accessible interval.
AppointmentTitleFormat is fed to a String.Format() call and supplies parameters for Start, End, Subject and Location in that order. So for example you could assign a string with a format like this:
480
AllowAppointmentMove and AllowAppointmentResize control if the user can drag or resize an appointment at runtime. To toggle visibility ofappointment status, all day appointment statusand navigation elements use the ShowAppointmentStatus, ShowAllDayAppointmentStatus andShowNavigationElements properties.
481
Changebetween views by changing the ActiveViewType property to one of the SchedulerViewType enumeration members. [VB] Assigning the ActiveViewType radScheduler1.ActiveViewType = SchedulerViewType.Day [C#] Assigning the ActiveViewType radScheduler1.ActiveViewType = SchedulerViewType.Day; Retrieve the view that is currently being displayed by using the ActiveView property, cast it to be the ActiveViewType [VB] Using the ActiveView Property radScheduler1.ActiveViewType = SchedulerViewType.Month (TryCast(radScheduler1.ActiveView, SchedulerMonthView)).WeekCount = 2 [C#] Using the ActiveView Property radScheduler1.ActiveViewType = SchedulerViewType.Month; (radScheduler1.ActiveView as SchedulerMonthView).WeekCount = 2;
482
Detect changes to the view by handling the ActiveViewChanging and ActiveViewChanged events. As always, the "Changing" event arguments provide the ability to cancel the view change,but also the "old" and "new" views before and after the view changes transpires: [VB] Handling the ActiveViewChanging Event Private Sub radScheduler1_ActiveViewChanging(sender As Object, e As SchedulerViewChangingEventArgs) lblStatus.Text = [String].Format("Old: {0} New: {1}", e.OldView.ViewType.ToString(), e.NewView.ViewType.ToString()) End Sub [C#] Handling the ActiveViewChanging Event private void radScheduler1_ActiveViewChanging(object sender, SchedulerViewChangingEventArgs e) { lblStatus.Text = String.Format("Old: {0} New: {1}", e.OldView.ViewType.ToString(), e.NewView.ViewType.ToString()); } In this walkthrough you will dynamically change the view, change some of theview specific properties and handle theActiveViewChanging event.
Project Setup
You can find the complete source for this project at: \Scheduler\<VB|CS>\Views 1. Create a new Windows Forms application. 2. In the Solution Explorer, delete the default form. 3. Also in the Solution Explorer, right-click the project and select Add | New Item... from the context menu. 4. Select the "Telerik RadForm" template and click the Add button to close the dialog. 5. Add the DesertTheme from the ToolBox to the form. 6. In the Properties window, set the formThemeName to Desert. 7. Add a RadStatusStrip to the form. Set the ThemeName to Desert. Add a RadLabelElement to the status strip. Set the Name property to "lblStatus" and the Text to "". 8. Add a RadCommandBar to the form.Add elements to the command bar strip:
483
Using thecontext menu, add a CommandBarDropDownList to the new row.Set the Name to "ddActiveViewType" and Text to "". Using thecontext menu, add a CommandBarDropDownList to the new row.Set the Name to "ddRange" and Text to "". Using thecontext menu, add a CommandBarDropDownList to the new row.Set the Name to "ddCount" and Text to "".
9. Change the new RadForm1 to be the startup form. 10. From the Toolbox, add a RadScheduler to the form and set the Dock property to "Fill" and the ThemeName to Desert. 11. Add code to the form load that will add values to the combo boxes in the tool strip for SchedulerViewType and ScaleRange enumerations. Also, add a simple range of integers to the "count" combo box. [VB] Handling the Load Event Private Sub RadForm1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load For Each viewType As SchedulerViewType In System.Enum.GetValues(GetType(SchedulerViewType)) Dim item As RadListDataItem = New RadListDataItem() item.Text = viewType.ToString() item.Value = viewType ddActiveViewType.Items.Add(item) Next viewType For Each range As ScaleRange In System.Enum.GetValues(GetType(ScaleRange)) Dim item As RadListDataItem = New RadListDataItem() item.Text = range.ToString() item.Value = range ddRange.Items.Add(item) Next range For i As Integer = 1 To 9 Dim item As RadListDataItem = New RadListDataItem() item.Text = i.ToString() item.Value = i ddCount.Items.Add(item) Next i End Sub [C#] Handling the Load Event private void RadForm1_Load(object sender, EventArgs e) { foreach (SchedulerViewType viewType in Enum.GetValues(typeof(SchedulerViewType))) { RadListDataItem item = new RadListDataItem(); item.Text = viewType.ToString(); item.Value = viewType; ddActiveViewType.Items.Add(item); } foreach (ScaleRange range in Enum.GetValues(typeof(ScaleRange))) { RadListDataItem item = new RadListDataItem(); item.Text = range.ToString(); item.Value = range; ddRange.Items.Add(item); }
484
485
486
Using Resources
Add resources by using the Resources collection Add() method and passing a new Resource instance. Pass a unique ID and adescription in the constructor. [VB]Adding Resources Private Sub LoadResources() Dim descriptions As String() = {"Conference Room 112", "Conference Room 113", "Meeting Hall A2"} Dim count As Integer = 1 For Each description As String In descriptions radScheduler1.Resources.Add(New Resource(System.Math.Max
487
A Resource object also has an Image property that isdisplayed in the resource selection control.
488
489
490
491
492
493
494
Recurring Appointments
Create specialized RecurrenceRule descendants to implement recurrence for specific intervals:
One of several constructor overloads lets you set the start time, duration and number of occurences. Then the rule can be assigned to the appointments RecurrenceRule property. The snippet below defines a rule thatstarts "now" and recurs every two hoursand stops after thetenth occurrence. [VB] Adding a RecurrenceRule radScheduler1.Appointments(0).RecurrenceRule = New HourlyRecurrenceRule(DateTime.Now, 2, 10) [C#] Adding a RecurrenceRule radScheduler1.Appointments[0].RecurrenceRule = new HourlyRecurrenceRule(DateTime.Now, 2, 10); The Appointment Occurrences property lets you iterate a list of IEvent instances. To get only some occurrences between specific starting and stopping times, use the Appointment GetOccurrences() method. [VB] Iterating Occurrences ' iterate all appointment occurrances '... For Each ev As IEvent In recurringAppointment.Occurrences Next ' iterate only occurrances after 10am
495
496
1. In a new application, add a RadScheduler and two RadListControls to the form. Place the RadScheduler on the left half of the form and the two RadListControls on the right half of the form, one above the other. Name the first list box "lcAll" and the second "lcAfter10". 2. Add the code below to the form's Load Event handler: [VB] Adding and Traversing Appointment Recurrences Private Sub RadForm1_Load(sender As Object, e As EventArgs) Dim startDate As New DateTime(2008, 10, 1, 3, 30, 0) ' Create a sample appointment that starts at 10/1/2008 3:30 AM and lasts half an hour. Dim recurringAppointment As New Appointment(startDate, TimeSpan.FromHours(1), "Appointment Subject") ' Create a recurrence rule to repeat the appointment every 2 hours for 10 occurrences. Dim rrule As New HourlyRecurrenceRule(recurringAppointment.Start, 2, 10) 'Assign the hourly recurrence rule to the appointment recurringAppointment.RecurrenceRule = rrule radScheduler1.Appointments.Add(recurringAppointment) ' iterate all appointment occurrances For Each ev As IEvent In recurringAppointment.Occurrences lbAll.Items.Add(New RadListBoxItem(ev.Start.ToShortTimeString() + " - " + ev. [End].ToShortTimeString())) Next ' iterate only occurrances after 10am Dim occurrencesAfter10AM As IEnumerable(Of IEvent) = recurringAppointment.GetOccurrences (New DateTime(2008, 10, 1, 10, 0, 0), DateTime.Now) For Each ev As IEvent In occurrencesAfter10AM lbAfter10.Items.Add(New RadListBoxItem(ev.Start.ToShortTimeString() + " - " + ev. [End].ToShortTimeString())) ' set the background id to "Important" and make this occurence an "Exception" ev.BackgroundId = DirectCast(AppointmentBackground.Important, Integer) ev.StatusId = DirectCast(AppointmentStatus.Tentative, Integer)
497
498
You can find the complete source for this project at: \Scheduler\<VB|CS>\DragAndDrop The first part that differs is the RadScheduler DragDrop event handler. Here you need to get the location of the mouse and convert it to a point that the scheduler can use to get the cell element underneath the mouse. This MonthCellElement is passed to a private method GetCellAppointment() that we will write next. [VB] Drop to the Month Cell Element Private Sub radScheduler1_DragDrop(ByVal sender As Object, ByVal e As DragEventArgs) Handles radScheduler1.DragDrop Dim scheduler As RadScheduler = TryCast(sender, RadScheduler) ' get mouse location on the screen Dim mouseLocation As System.Drawing.Point = New System.Drawing.Point(e.X, e.Y) ' convert to location on the sceduler Dim schedulerLocation As System.Drawing.Point = scheduler.SchedulerElement.PointFromScreen (mouseLocation) ' get the cell element for the location Dim element As RadElement = scheduler.ElementTree.GetElementAtPoint(schedulerLocation) ' cast cell element to MonthCellElement and create an appointment for cell date If (Not element Is Nothing) AndAlso (TypeOf element Is MonthCellElement) Then Dim monthCellElement As MonthCellElement = TryCast(element, MonthCellElement) Dim appointment As Appointment = GetCellAppointment(monthCellElement) scheduler.Appointments.Add(appointment) End If ' finished drop, clear temporary variables _dragRectangle = Rectangle.Empty _currentItem = Nothing
499
500
19.6 Summary
This chapter explored RadScheduler capabilities: how to bind data to the scheduler, add, remove and iterate appointments, work with resources, modify the view (i.e. week, day, month) and manipulate appointment status. The chapter also demonstrated how to drag and drop appointments into the scheduler.
501
20.1 Objectives
Become familiar with RadChart by building a simple chart with static items and another basic chart using bound data. Take a tour of the basic elements of each RadChart and the available types of charts. Learn how designer interface tools help organize RadChart capabilities. Learn about some of the latest RadChart features. Create chart series and chart series items programmatically. Learn the specifics of data binding in RadChart.
20.2 Introduction
RadChart is a powerful business data presentation tool that can show your data off with striking impact. RadChart comes with many customizable chart types and skins to tailor the behavior and look of each chart. You can choose fine-tune control over all aspects of your chart or use the automatic layout, automatic text wrapping and intelligent labeling functions to handle the details. At design time you get quick access to critical properties with the Smart Tag, convenient groups of important properties in the RadChart wizard, or control all RadChart settings from the Properties Window. The focus of this chapter will be in organizing the many capabilities and properties of this rich control so that you can get maximum use out of it from the outset.
502
5. Click the ellipses button of the Items property to open the ChartSeriesItem Collection Editor. 6. Click the Add button to add a new Item. 7. In the property window for the new item, change the Name property to "Beverages". 8. Change the YValue property to "10000".
9. Repeat the Add Item steps to add 3 new items. Replace the properties for the three new items as follows:
503
10. Click OK to close the ChartSeriesItem Collection Editor. 11. Click "Series 2" in the ChartSeries Collection Editor. 12. Click the Remove button to remove Series 2. 13. Click the OK button to close the ChartSeries Collection Editor. 14. The chart will display the new data using the default formatting.
504
4. In the Properties window, set the AutoLayout property to "true". Notice that the AutoLayout feature of RadChart makes the best use of the form real-estate andexpands the chart content as much as possible. 5. Press Ctl-F5 to run the application. The chart title "Category Sales" should appear at the top of the chart.
505
From the Smart Tagopen theChoose Data Source drop down and select Add Project Data Source... from the list. In the "Choose a Data Source Type" page of the wizard, select the Database icon, then click the Next button to continue. In the "Choose your data connection" page of the wizard, click the New Connection... button. This step will bring up the Add Connection dialog. In the Add Connection dialog, the Data Source entry should read "Microsoft Access Database File (OLE DB)" (see screenshot below). If it is not, click the Change... button and select "Microsoft Access Database File (OLE DB)" from the list. Also in the Add Connection dialog, click the Browse... button, navigate to the RadControls for Winforms installation and locate the \Examples\QickStart\DataSources directory. Open the "Nwind.mdb" file. Click OK to close the Add Connection dialog.
506
Back at the "Choose Your Data Connection" page of the wizard, click the Next button to continue. You will receive a dialog popup with message "The connection you selected is a local file...". Click Yes to close the dialog and copy the data file locally. In the Choose Your Database Objects page, open the treeview "Views" node, locate the "Sales by Category" view and check the "CategoryName", "ProductName" and "ProductSales" columns. Click the Finish button to close the dialog. This last step will create a DataSet, TableAdapter and BindingSource and place them in the components tray.
Locate the "sales_by_CategoryTableAdapter" component in the component tray. Open the Smart Tag and select Edit Queries in DataSet Designer... Locate the "Fill, GetData()" element of the "Sales by CategoryTableAdapter", right-click and select Configure... from the drop down menu. This step will display the TableAdapter Configuration Wizard dialog.
In the TableAdapter Configuration Wizard "Enter a SQL Statement" page, enter the SQL below, then click Finish toclose the dialog.This query groups the sales figure by category and provides total sales for each group. [SQL] Retrieve sales by category data SELECT CategoryName, SUM(ProductSales) AS ProductSales FROM [Sales by Category] GROUP BY CategoryName ORDER BY SUM(ProductSales) DESC
3. From the Smart Tagselect theChart Wizard link from the Setting section.
507
5. In the Data tab of the wizard set the Y values drop down list to "ProductSales" and the X-Axis to "CategoryName". In a horizontal bar chart, the X-Axis will list the category names from top to bottom on the left hand side of the chart.
508
7. In the Labels, Legend & Title tab, set the Series Labels to "ProductSales" from the drop down list,deselect the Legend Visible check box. Set the Title Text to "Sales by Category"
8. In the Axis tab of the wizard, select the "Y Axis" from the drop down list. Then set the Rotation to "40". This will spin the labels clockwise 40 degrees so that they will not overlap.
509
9. Click the OK button to close the wizard. 10. In the Properties window set the RadCalendar AutoLayout property to "true". 11. Press Ctl-F5 to run the application. Notice that the labels on the X-axis are arranged from top to bottom on the left hand side in this horizontal layout. If the layout were vertical, the labels would be listed along the bottom.Also notice that the labels at the bottom of the chart are spun 40 degrees clockwise to prevent overlap.
510
Chart Background
The background of the chart is the outermost rectangle that encloses all other elements of the chart. It stretches for the whole width and length of the output image of the chart.
511
Appearance: This is an extensive property, also found attached to other properties throughout the chart. The exact makeup of Appearance changes depending on the context you find it in. Appearance lets you customize all the visual aspects of the chart element you're working with, such as layout, dimensioning, positioning, fill, background images, font colors and borders. The appearance properties for the ChartTitle are shown below. Here we're setting the RotationAngle to -20.
You can see the effect where the title is rotated 20 degrees to the left:
Marker: Controls a small graphic for whatever area is being described, e.g. title, legend, etc. By default the marker is not visible. Notice that the Marker property has it's own Appearanceproperty nested within.In the example below we've set the Figure property to "Star3" and the Visible property to true.
512
These property settings place a small rightward-pointing graphic to the left of the title.
TextBlock: lets you fine-tune the appearance of the text, the visibility of the text and the text string itself. In the example below we add a border set to the AliceBlue color.
The TextBlock.Appearance.Border property setting was applied to the ChartTitle to get this appearance:
513
Plot Area
The plot area is the working rectangular area between X and Y axes where data is displayed. This property isa major jumping off point for configuring the axis of the chart.
The size of the plot depends on the chart background size and the chart margins, which define the distance between the border of the plot area and the border of the chart background.
514
The PlotArea DataTable displays a spreadsheet style table of the data in the chart, typically just below the chart itself. You can see in this screenshot that the data for both series is displayed in the table at the bottom of the chart.
The PlotArea EmptySeriesMessage is a predefined message that displays in the PlotArea when there is no series data defined for the chart. MarkedZones are areas in the background of the chart that can be defined, labeled and filled. MarkedZones are used to highlight or group areas on the chart and by default display behind the chart series. You can create any number of members for the MarkedZones collection and each marked zone is defined by starting and ending X and Y value pairs. There are two marked zones displayed in the screenshot below that delineate extreme high and low temperatures.
515
Chart Series
Series contains a set of data points to be drawn on the chart. This set of points contains related data. Each series can be represented by a chart type. Pie charts use only a single series. For other chart types there is no limitation to the number of series or items within each series. The screenshot below shows two series named "Internet" and "WholeSale" defined within the ChartSeries Collection Editor.
Use "#Y" or "#X" to display numbers from the X or Y axis respectively Use "#%" for a percentage of the total sum (of all items). Use "#SUM" to display the total of all items. "#STSUM" displays the sum of a stacked series.
516
"#SERIES" displays the series name. "#ITEM" displays the item name. You can also use standard numeric format strings. Use curly brackets to contain the formats. For example, you can display Y values as currency by setting DefaultLabelValue to "#Y{C}".
Series Items
Each chart series item encapsulates a single data point within a chart series. For simple charts along a single axis, you can populate the YValue property only. Use the XValue property to add a second data dimension. For example, the Y values could represent "Sales Volume" and the X values might show time periods or geographic regions. The meaning of the XValue2 and YValue2 properties vary depending on the type of chart. For example XValue2 and YValue2 are used by Gantt type to indicate a period of time and the Bubble chart type to show amplitude of data.
Stacked Bar Stacked Bar charts are used to compare contributions of values to a total across categories.Use the Stacked Bar chart when you need visibility to the combined values for each category.
517
Area The Area chart consists of a series of data points joined by a line and where the area below the line is filled.Area charts are appropriate for visualizing data that fluctuates over a period of time and can be useful for emphasizing trends.
Stacked Area The Stacked Area chart is a variation of the Area chart that display trends of the contribution of each value over time (or across categories). The areas are stacked so that each series adjoins but does not overlap the preceding series. Area charts are appropriate for visualizing data that fluctuates over a period of time and where the entire area for all series data must be visible at one time.
Stacked Area 100% Stacked Area 100% charts are a variation of Stacked Area charts that present values for trends as percentages, totaling to 100% for each category. Use this chart type to visualize data that fluctuates over a period of time and where the relationship between values in a category is more significant than the amounts.
Pie The Pie chart shows slices representing fractional parts of a whole.
Gantt Gantt charts, also known as Time charts, display separate events as bars along a time scale.These charts are often used for project/time planning, where data can be plotted using a date-time scale or other numeric scale.
The Bezier chart displays a series of points on a curved line. Two "control points" determine the position and amount of curvature in the line between end points. The Bezier chart is often used for data modelling by taking a limited number of data points and interpolating or estimating the intervening values. Bezier
518
Spline Spline charts allow you to take a limited set of known data points and approximate intervening values.The Spline chart, like the Bezier, is often used for data modelling by taking a limited number of data points and interpolating or estimating the intervening values.
Bubble The Bubble chart is an extension of the Point chart but each point can be a circle or oval of any size or dimension. The bubble size may be used to convey larger values.The Bubble chart is often used for scientific data modeling or financial data.
Spline Area The Spline Area chart type defines one or more spline curves and fills in the area defined by the spline.This chart type can also can be used for data modelling in that it takes a limited number of data points and interpolates the intervening values.
Stacked Spline Area The Stacked Spline Area chart is a variation of the Spline Area chart. The areas are stacked so that each series adjoins but does not overlap the preceding series. Also can be used for data modelling in that it takes a limited number of data points and interpolates the intervening values. This chart type allows the entire surface area for all sequences to be displayed at one time. Stacked Spline Area 100% The Stacked Spline Area 100% chart is a variation of the Spline Area chart. The areas are stacked so that each series adjoins but does not overlap the preceding series and where the combined total for each category is 100 percent.The Stacked Spline Area 100% chart can also can be used for data modelling in that it takes a limited number of data points and interpolates the intervening values. This chart type allows the entire surface area for all sequences to be displayed at one time. Use this chart type when the relationship between values in a category is more significant than the amounts. Point or "Scatter" charts are used to show correlations between two sets of values. The Point chart is often used for scientific data modeling or financial data. The Point chart is typically not used used with time dependent data where a Line chart is more suited. Point
519
Line The Line chart type displays a set of data points connected by a line.A common use for the line chart is to show trends over a period of time.
CandleStick The CandleStick chart combines bar and line chart styles to show a range of value movement over time. Dark colored bars show downward trends, light colored bars show upward trends and the line through the center (the "wick") shows the extreme high and low values.Use this chart type to visualize price or currency fluctuations. Typically this chart is used to analyze stock prices or currency changes.
Stacked Line
Stacked Spline The Stacked Spline chart, line the Stacked Line, lets you have multiple series of Y values. It can take a limited number of data points and interpolate the intervening values.
520
Layout
At the top of the Smart Tag in the Layout section, you can set the Width and Height of the chart as a whole.
Appearance
Below the Layout area, you can use the Appearance section to quickly set the
Title Text Chart Series Orientation to Horizontal or Vertical from the drop down list. Default Chart Type to one of the chart types in the drop down list, i.e.Bar, Pie, Line or any of the types we reviewed in the Getting Started section. Skin can be set from the drop down list to quickly style the entire look of the chart.
Data
You can bring up the Chart Series collection editor from the ellipses if you want to statically define series and items directly at design time. If you want to bind data, select a data source from the drop down list. If no data sources exist in the project yet, select "<New Data Source...>" from the drop down list.
Chart Wizard
Click this link to display the Chart Wizard.
Chart Wizard
The RadChart Wizard helps you traverse the many properties of RadChart by providing the most commonly used properties in an intuitive way. The wizard can help you quickly set up the basic structure of your chart. The Wizard functions are arranged in tabs:
Type Tab
The Type tab lets you quickly choose the chart type by providing visual cues to what each type looks like. Here you can also choose the chart orientation.
521
Data Tab
The Data tab brings together the Series, Series Item, Axis labels and data binding to a single screen. Here you can add data points to your chart manually or by binding to data sources.
522
Group Column
The Group Column appears on the upper right side. Select a column name from a bound data source to group by that column data.
Series
Use the Series area of the tab to add, delete and reorder chart series elements using the list box provided. Use the plus and minus buttons to add or delete a series element. Use the up and down arrows to move a series element up or down in the list. For each selected series element in the list box you can provide a name and select from the list of chart types. If you bind to a data source, the Databind Series Elements portion will be enabled and allow you to choose column names for your labels and values from the drop down lists provided.If you need to fine tune the behavior or appearance of a series in more depth than the Data tab provides, use the RadChart Series property in the property window.
Series Items
For each series you select in the Series Items list, you can add, edit, delete and reorder entries. Use the plus and minus buttons to add and delete series items. Use the up and down arrows to move series items up or down in the list. For each item you can set the Name, Label and X and Y Values. X2 and Y2 values are enabled for Gantt and Bubble chart types.
Axis Labels
This section lets you choose between binding to a column in the data source and using the column data to populate the labels along an Axis. Click the Add Labels Manually link to navigate to the Axis tab.
Skin Tab
The RadChart Skin property lets you apply a coordinated set of style changes to all the chart visual aspects at one time. The Skin tab lets you inspect how a chart might look with a given skin. The skins displayed reflect the current chart type.
523
Series Labels
524
Legend
Un-select the Visible check box to hide the legend. Use the Marker drop down to select from a predefined list of shapes, e.g. Cross, Diamond, Ellipse, Rectangle, etc.Use the Alignment drop down to move the legend position between None, Left, Top, Bottom, Center, TopRight, TopLeft, BottomRight and BottomLeft.
Title
The Title section lets you set the text andtoggle visibility of the chart title.Use the Alignment drop down to move the title position between None, Left, Top, Bottom, Center, TopRight, TopLeft, BottomRight and BottomLeft.
Axis Tab
From this tab you canselect an axis from the drop down list at the top of the page. Properties you modify will be retained for the selected axis. Use the Copy Settings From button to replicate settings from another axis.
Visual Properties
The Visual Properties section of the page controls properties for the axis as a whole. Uncheck the Visible checkbox to hide the entire axis (including labels and tick marks). The Axis Title text populates a single label that appears for the axis as a whole. Use the Alignment property to place the axis label in a predefined position, e.g. Left, Right, Top, Bottom, Center, TopRight, TopLeft, BottomRight, BottomLeft. Un-check Show Ticks to hide the axis tick marks. Un-check Show Labels to hide the axis labels (but not the Axis Title). The Value Format drop down list automatically formats axis labels as various kinds of dates, times, percentages, numbers and currency. Visible Values can be All, Positive or Negative values. Rotation is used to rotate the axis label text. Positive numbers spin the labels clockwise, negative numbers counter-clockwise.
525
Visual Properties
Check Visible to display the chart data table. By default this is unchecked. Select Draw Type from the drop down list to control the general size and positioning of the chart:
Select AutoSize to have each cell size to the data inside of it. PlotAreaRelative places each cell just below the chart series item it represents. CellFixedSize and TableFixedSize fix the size of the cells or table irrespective of the data it contains.
Alignment
Use the Align drop down list to place the chart data table in a predefined position (e.g. Top, Bottom, BottomRight, etc.) To place the data table at exact coordinates, un-check Auto and enter values for X and Y.
Properties Window
At design time, you can use the Properties Window to configure almost every aspect of the chart.You will need to build a mental map ofhow the critical properties arearranged. At the top level the critical properties are ChartTitle, DataSource/DataMember,Legend, PlotArea and the Series collection. Within the Series collection
526
527
[VB] Adding a Chart Series and Items Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) radChart1.AutoLayout = True ' Create the series and assign the ChartSeriesType radChart1.Series.Clear() Dim chartSeries As New ChartSeries("Average Temperatures", ChartSeriesType.Bar) ' Define the items in the series chartSeries.AddItem(5) chartSeries.AddItem(1) chartSeries.AddItem(-1) chartSeries.AddItem(-5) chartSeries.AddItem(-7) ' add an empty item Dim isEmpty As Boolean = True Dim item As New ChartSeriesItem(isEmpty)
528
One frequently asked question about RadChart is "how do I explicitly label one of the axis"? You do that by turning off the AutoScale property and adding your own axis array members. In this example we will add the short day names along the bottom of the chart. A second question is "all the values seem to scrunch up too high in the chart". The remedy here is to set the YXis AxisMode to"Extended" for a little more headroom.
529
You can find the complete source for this project at: \Chart\<VB|CS\Programming2 1. Create anWindows FormsApplication. 2. From the Toolbox drag a RadChart component to the form. 3. Begin coding the Form_Load handler by setting up thelabel and chart title. For the legend you need to shut off the Appearance.Position.Auto property so that you can explicitly position the legend exactly where you want it. You could also have used one of the predefined positions, hidden the legend or set theAppearance fill to a transparent color so you could seethrough to the data points beneath. The ChartTitle is positioned to theupper left andtheText is"Weekly Forecast". [VB] Defining the Chart Legend and Title Protected Sub Form_Load(ByVal sender As Object, ByVal e As EventArgs) ' Configure the Legend and Chart Title labeling radChart1.Legend.Appearance.Position.Auto = False radChart1.Legend.Appearance.Position.X = 220 radChart1.Legend.Appearance.Position.Y = 50 radChart1.ChartTitle.Appearance.Position.AlignedPosition = Telerik.Charting.Styles.AlignedPositions.TopLeft radChart1.ChartTitle.TextBlock.Text = "Weekly Forecast" '... End Sub [C#] Defining the Chart Legend and Title protected void Form_Load(object sender, EventArgs e) { // Configure the Legend and Chart Title labeling radChart1.Legend.Appearance.Position.Auto = false;
530
[VB] Configuring the XAxis ' Configure the XAxis radChart1 .PlotArea.XAxis.AutoScale = False radChart1 .PlotArea.XAxis.AddRange(1, 7, 1) radChart1 .PlotArea.XAxis(0).TextBlock.Text radChart1 .PlotArea.XAxis(1).TextBlock.Text radChart1 .PlotArea.XAxis(2).TextBlock.Text radChart1 .PlotArea.XAxis(3).TextBlock.Text radChart1 .PlotArea.XAxis(4).TextBlock.Text radChart1 .PlotArea.XAxis(5).TextBlock.Text 6. radChart1 .PlotArea.XAxis(6).TextBlock.Text [C#] Configuring the XAxis
= = = = = = =
531
7. Configure the YXis AxisMode to Extended so that there is a little more room at the top of the chart. Set the Text for the AxisLabel.TextBlock to "Temperature C" and the Appearance.Width to "3". [VB] Configure the YAxis ' Configure the YAxis radChart1 .PlotArea.YAxis.AxisMode = ChartYAxisMode.Extended radChart1 .PlotArea.YAxis.AxisLabel.TextBlock.Text = "Temperature C" [C#] Configure the YAxis // Configure the YAxis radChart1 .PlotArea.YAxis.AxisMode = ChartYAxisMode.Extended; radChart1 .PlotArea.YAxis.AxisLabel.TextBlock.Text = "Temperature C"; 8. Clear the chart Series collection to remove the default two series that show up at design time when you add the chart to the page. Create a new ChartSeries with name "Average Temperatures" andtype "Bar". Set the main color for the series Appearance FillStyleto "HoneyDew" and the secondary color to "Green". [VB] Add the Chart Series ' Create the series and assign the ChartSeriesType radChart1 .Series.Clear() Dim chartSeries As New ChartSeries("Average Temperatures", ChartSeriesType.Bar) chartSeries.Appearance.FillStyle.MainColor = System.Drawing.Color.Honeydew chartSeries.Appearance.FillStyle.SecondColor = System.Drawing.Color.Green [C#] Add the Chart Series // Create the series and assign the ChartSeriesType radChart1 .Series.Clear(); ChartSeries chartSeries = new ChartSeries("Average Temperatures", ChartSeriesType.Bar); chartSeries.Appearance.FillStyle.MainColor = System.Drawing.Color.Honeydew; chartSeries.Appearance.FillStyle.SecondColor = System.Drawing.Color.Green; 9. Add the code below to the end of the Form_Load event handler: Add the data points to the first series by using the AddItem() method of the chart series and passing Y values. [VB] Adding Chart Series Items ' Define the items in the series chartSeries.AddItem(5) chartSeries.AddItem(1) chartSeries.AddItem(-1) chartSeries.AddItem(-5) chartSeries.AddItem(-7) chartSeries.AddItem(-3) chartSeries.AddItem(-1) radChart1.Series.Add(chartSeries); [C#] Adding Chart Series Items
532
10. Add the code below to the end of the Form_Load event handler:Add a second series with name "Maximum Temperatures" and type "Line". Hide the labels by setting the series Appearance.LabelAppearance.Visible to "false". Set the LineSeriesAppearance Color to "Red". [VB] Create and Configure Line Series ' Create a second series and assign the ChartSeriesType Dim chartSeries2 As New ChartSeries("Maximum Temperatures", ChartSeriesType.Line) chartSeries2.Appearance.LabelAppearance.Visible = False chartSeries2.Appearance.LineSeriesAppearance.Color = System.Drawing.Color.Red [C#] Create and Configure Line Series // Create a second series and assign the ChartSeriesType ChartSeries chartSeries2 = new ChartSeries("Maximum Temperatures", ChartSeriesType.Line); chartSeries2.Appearance.LabelAppearance.Visible = false; chartSeries2.Appearance.LineSeriesAppearance.Color = System.Drawing.Color.Red; 11. Add the code below to the end of the Form_Load event handler. Again, chart series items are added to the second series by calling AddItem() with Y values as parameters. [VB] Add Items to the Second Series ' Define the items in the series chartSeries2.AddItem(11)
533
[VB] Enhance the "Maximum Temperature" Data Points ' visually enhance the data points chartSeries2.Appearance.PointMark.Dimensions.Width = 5 chartSeries2.Appearance.PointMark.Dimensions.Height = 5 chartSeries2.Appearance.PointMark.FillStyle.MainColor = System.Drawing.Color.Black chartSeries2.Appearance.PointMark.Visible = True [C#] Enhance the "Maximum Temperature" Data Points // visually enhance the data points chartSeries2.Appearance.PointMark.Dimensions.Width = 5; chartSeries2.Appearance.PointMark.Dimensions.Height = 5; chartSeries2.Appearance.PointMark.FillStyle.MainColor = System.Drawing.Color.Black; chartSeries2.Appearance.PointMark.Visible = true; 13. Add a third "Minimum Temperatures"series, add items and set the PointMark appearance for the series. This code is very similar to the code for the second "Maximum Temperatures" series except that the colors and Y values are different. [VB] Add the "Minimum Temperatures" Series ' Create a third series and assign the ChartSeriesType Dim chartSeries3 As New ChartSeries("Minimum Temperatures", ChartSeriesType.Bubble) chartSeries3.Appearance.LabelAppearance.Visible = False chartSeries3.Appearance.FillStyle.MainColor = System.Drawing.Color.Blue
534
Data Binding
RadChart data binding works similarly to other RadControls in that you can bind the same basic types, consume the same data source controls and can assign the DataSource property. The control-specific differences are in the properties used to specify what columns are bound to particular displays and behaviors in the chart. RadChart uses the same basic underlying engine for Windows, Web and Reporting versions.
535
The ChartSeries DataLabelsColumn supplies the text that displays on top of each series item. The XAxis also has a DataLabelsColumn propertythat displays text next to each X Axis item.
536
You can run into a problem if IntelligentLabelsEnabled is set to true, moving the labels too far away from their respective data points, thus making the chart harder to interpret. Setting the ChartSeries Appearance.ShowLabelConnectors property to true displays the lines between the labels and the data points.
As the items are bound, the labels are formatted based on the ranges of values the data points fall within. [VB] Handling the ItemDataBound Event Protected Sub radChart1_ItemDataBound(ByVal sender As Object, ByVal e As Telerik.Charting.ChartItemDataBoundEventArgs) Dim qty As Integer = Convert.ToInt32((TryCast(e.DataItem, DataRowView))("TotalQuantity")) Dim quantityLabel As String = [String].Empty Select Case qty Case 1, 2 quantityLabel = "Few" Exit Select Case 3 quantityLabel = "Some" Exit Select Case 4, 5
537
538
Data with columns "Year", "Quarter" and "Value" "Year" contains multiple rows for "2011" and "2012". The DataGroupColumn property is "Year".
...then there will be two series, one for "2011" and the second for "2012". A second RadChart property, GroupNameFormat, defines a format for the legend item. The format can have free text and can include two special words:
#NAME: denotes the group column name. #VALUE: denotes the group column value (it is the same for all the records shown in the same series).
The SQL below gets a sampling of Invoice data and brings back the CustomerID, ExtendedPrice and Quantity. [T-SQL] Selecting Invoice Data SELECT TOP (25) CustomerID, ExtendedPrice, Quantity FROM Invoices ORDER BY CustomerID The "ORDER BY" clause is important for group queries. If the data in the example above was unordered, you would get a group for the first few records of customer "ALFKI", then a few records for "ANATR", then perhaps another bar for the next few "ALFKI" customer again. In typical cases adding the ORDER BY clause will give you the results you expect. The screenshot below shows the DataGroupColumn set to "CustomerID". No series is set and the DataYColumn property of the series is not set. The actual values shown in the bar are derived from the last numeric column in the datasource. In the figure below the "Quantity" data shows in the chart.
539
Gotcha! Don't define the series DataYColumn as it will take precedence over the group property settings.
Using the Year/Quarter/Value data mentioned above and if we set the GroupNameFormat to "#NAME: #VALUE", the legend will be "Year: 2011" and "Year: 2012". We can build this example by first creating a class to contain the Year/Quarter/Value, populating a generic list of these objects, setting the group properties and finally binding to the chart. You can find the complete source for this project at: \Chart\<VB|CS>\Grouping 1. Create a new Windows Forms application. 2. From the Toolbox drag a RadChart component to the form. 3. Add a simple "Sales" class either to the form code or to a separate Sales.cs file with the following class definition: 4.
540
541
542
Use the axis DataLabelColumn property to add meaningful labels to the data across the bottom of this chart. If we had a property/column "QuarterDescription" with values "Qtr 1", "Qtr 2"..., these could be used in place of the number 1, 2...
Set the axis AutoScale property off so you can manually populate. Set the axis Appearance.ValueFormat using the ChartValueFormat enumeration. For example, you can use the ShortDate or ShortTime to format the axis. Add a range of DateTime values, being careful to convert them with the ToAODate() method.
Here's a short code example that labels the XAxis with a series of dates: [VB] Adding a Range of Dates radChart1.PlotArea.XAxis.AutoScale = False radChart1.PlotArea.XAxis.Appearance.ValueFormat = ChartValueFormat.ShortDate radChart1.PlotArea.XAxis.AddRange(today.ToOADate(), today.AddDays(10).ToOADate(), 1) [C#] Adding a Range of Dates radChart1.PlotArea.XAxis.AutoScale = false; radChart1.PlotArea.XAxis.Appearance.ValueFormat = ChartValueFormat.ShortDate; radChart1.PlotArea.XAxis.AddRange(today.ToOADate(), today.AddDays(10).ToOADate(), 1); Here's a slightly longer example that shows a gantt chart with a series of dates on the X axis and a series of times on the Y axis.
543
You can find the complete source for this project at: \Chart\<VB|C#>\DateTimeOnNumericAxis 1. In a new WinForms project, add a RadChart to the default form. 2. In the code behind, add a private method GetDataTable() that will generate and return a four column table with sample values. Notice that the data values are also converted to OLE Automation types before storing. [VB] Generating the Data ' generate a four column table with sample ' date and time data stored as doubles Private Function GetDataTable() As DataTable Dim input As Double(,) = New Double(3, 2) {{8, 12}, {9, 14}, {13, 18.5}} Dim table As New DataTable() table.Columns.Add("X", GetType(Double)) table.Columns.Add("X2", GetType(Double)) table.Columns.Add("Y", GetType(Double)) table.Columns.Add("Y2", GetType(Double)) Dim start As DateTime = DateTime.Today Dim i As Integer = 0 While i < 3 Dim row As DataRow = table.NewRow() ' convert all dates and times to OLE Automation dates ' which are stored as doubles row("X") = start.AddDays(i).ToOADate() row("X2") = start.AddDays(i + 1).ToOADate() row("Y") = start.AddHours(input(i, 0)).ToOADate() row("Y2") = start.AddHours(input(i, 1)).ToOADate() table.Rows.Add(row) System.Math.Max(System.Threading.Interlocked.Increment(i),i - 1) End While Return table End Function [C#] Generating the Data // generate a four column table with sample
544
545
Events
Use the BeforeLayout event when you want to safely customize layout-related properties. BeforeLayout will correctly display without clipping because layout arrangements occur after this event. All the elements of the chart exist before this event fires, so you can make changes to items, axis, legend, etc., as in this example below. The form Load event makes a little extra room for the new labels. The BeforeLayout event handler sets the chart legend border and cycles through the Y axis text blocks, sets a custom stringand rotates the axis item 20 degrees. [VB] Handling the BeforeLayout Event Private Sub Form1_Load(sender As Object, e As EventArgs) radChart1.PlotArea.Appearance.Dimensions.Margins.Left = New Telerik.Charting.Styles.Unit (30, Telerik.Charting.Styles.UnitType.Percentage)
546
547
Scale Breaks
The ScaleBreaks feature allows you to "break off" large chunks of the axis so that graphs with large amplitude are easier to read. ScaleBreaks are available for both YAxis and YAxis2 properties of the PlotArea. You can tailor the maximum number of breaks, the minimum interval between data points before a break can occur, the visual size of the breaks and the visual style of the breaks.
Multi-Line Labels
Labels in RadChart can appear on multiple lines. For example, the property editor for TextBlock. Text properties allows you to hit the enter key to start a new line. Press control-enter to accept the text and close the property editor.
548
Strict Mode
"strict mode" is not a property or setting, but a behavior of bar chart series where X values are respected and bars are positioned according to their XValues. If there are no series items with XValues then RadChart resumes standard sequential ordering of each item. The screen shot below was produced using the X and Y values from this table: Series 1 (Blue) YValue 3 3 4 3 5 Series 2 (Orange) YValue 1 2 XValue 0 1 3 3 4 XValue 5 4
549
Logarithmic Y-Axis
RadChart's Y-Axis now supports logarithmic mode. This is convenient when you would like to display rapidly increasing values. Set theYAxis or YAxis2 IsLogarithmic property (false by default) to true to enable this behavior. The LogarithmBase property (10 by default) can be increased to further compress the presentation of values.
20.7 How To
Drill-Down
RadChart can be configured to handle "drill-down" functionality where the initial presentation of the chart presents the "Mile HighView" of data where the information shows the most general, highest level scope of data. Then the user clicks on a chart element and "drills down" to the next level of specificity. For example, if we have revenue by Year, Quarter and Month, the initial view will be the greatest time span, which is year. The year is divided into quarters. By clicking on an item on the chart you can see the values correspoding to the quarters of the selected year. Each quarter consists of 3 months. After choosing a quarter for the selected year you can see the values for each month of the quarter. To test this you can use the Chart.mdb file in the RadControls for Winforms installation directory under \Examples\DataSources. Chart.mdb contains a "Revenue" table. Select the Year, Quarter, Month and Revenue columns.
550
From the Smart Tagopen theChoose Data Source drop down and select Add Project Data Source... from the list. In the "Choose a Data Source Type" page of the wizard, select the Database icon, then click the Next button to continue. In the "Choose your data connection" page of the wizard, click the New Connection... button. This step will bring up the Add Connection dialog. In the Add Connection dialog, the Data Source entry should read "Microsoft Access Database File (OLE DB)" (see screenshot below). If it is not, click the Change... button and select "Microsoft Access Database File (OLE DB)" from the list. Also in the Add Connection dialog, click the Browse... button, navigate to the RadControls for Winforms installation and locate the \Examples\QuickStart\DataSources directory. Open the "Chart.mdb" file.
551
Click OK to close the Add Connection dialog. Back at the "Choose Your Data Connection" page of the wizard, click the Next button to continue. You will receive a dialog popup with message "The connection you selected is a local file...". Click Yes to close the dialog and copy the data file locally. In the Choose Your Database Objects page, open the treeview "Tables" node, locate the "Revenue" table and check the "Year", "Quarter", "Month"and "Revenue" columns. Click the Finish button to close the dialog. This last step will create a DataSet, TableAdapter and BindingSource and place them in the components tray. The next few steps will create table adapter methods used to fill the dataset by data for the year, month and quarter. These methods will be called from within your code when the chart is clicked.
2. Create a "FillByYear" data source query statement: 1. Locate the "revenueTableAdapter" component in the component tray. Open the Smart Tag and select Edit Queries in DataSet Designer... 2. Right-click the "FillBy" element and select Configure... from the context menu. 3. On the "Specify a SQL SELECT statement" page of the wizard, enter the following SQL statement and click the Next button to continue. [SQL] FillByYear SELECT [YEAR], SUM(Revenue) AS Revenue FROM Revenue GROUP BY [YEAR] 4. On the "Choose Methods to Generate" page of the wizard, check the "Fill a DataTable" option and set the Method name to "FillByYear". Un-check the "Return a DataTable" option. Click the Finish button to close the dialog. 3. Add a "FillByQuarter" data source query statement: 1. Right-click the RevenueTableAdapter and choose Add Query... from the context menu. This will display the TableAdapter Query Configuration Wizard. 2. On the "Choose aCommand Type"page of the wizard, select the "Use a SELECT statement to load data"option. Click the Next button to continue. 3. On the "Choose a Query Type" page of the wizard, select the "SELECT which returns rows" option. Click the Next button to continue. 4. On the "Specify a SQL SELECT statement" page of the wizard, enter the following SQL statement and click the Next button to continue. [SQL] FillByQuarter SELECT SUM(Revenue) AS Revenue, Quarter FROM Revenue WHERE [YEAR] = ? GROUP BY Quarter 5. On the Choose Methods to Generate page of the wizard, check the "Fill a DataTable" option and set the Method name to "FillByQuarter". Un-check the "Return a DataTable" option. Click the Finish button to close the dialog. 4. Add a "FillByMonth" data source query statement: 1. Right-click the RevenueTableAdapter and choose Add Query... from the context menu. This will display the TableAdapter Query Configuration Wizard. 2. On the "Choose aCommand Type"page of the wizard, select the "Use a SELECT statement to load
552
5. In the code for the form, add the following private variable to store the current year when its selected from the chart: [VB] Storing the Current Year 'stores the currently selected year Private _year As Integer [C#] Storing the Current Year //stores the currently selected year private int _year; 6. Add the following to the Form_Load event. This set of statements will fill the dataset initially with the "by year" data and configure the chart. Notice that the XAxis AutoScale is turned off so that MinValue and MaxValue settings can take effect. [VB] Handle the Form_Load Event Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Me.revenueTableAdapter.FillByYear(Me.chartDataSet.Revenue) ' remove the second, unused series radChart1.Series.RemoveAt(1)
553
554
555
20.8 Summary
In this chapter you built a simple chart with static items and also learned how to bind data to the chart. You took a tour of the basic RadChart elements as well as the types of charts that are available. You learned how to use the tools in the designer to help navigate the many RadChart capabilities.You created and configured many of the chart elements programmatically, including the chart series, items, legend and chart title.
556
21.1 Objectives
Get familiar with theRadGridView control by binding to a data source and configuring the grid using the Property Builder. Learn how to add columns for any data type at design-time and using code. Learn how to group, filter and sort data based on user input at runtime, design-time configuration and using code. Display hierarchical data from multiple related tables in the grid. Get low-level programmatic control over the RadGridView update process using Virtual Mode. Learn to use RadGridView with LINQ data sources to implement dynamic paging, sorting, and filtering on large datasets. Export RadGridView data.
21.2 Introduction
RadGridView is a powerful, highly performant grid component from Telerik developed on top of the innovative Telerik Presentation Foundation, which allows for unprecedented combination of performance, extensibility, customizability, and ease of use.
Hierarchical data presentation - RadGridView has the ability to represent hierarchical master-detail data. Its hierarchical schema could be set up either at design-time, at runtime using the control API, or handled automatically for you based on the structure of the data.
557
Easily customizable theming mechanism - RadGridView is shipped with a consistent set of themes that allow you to easily build slick interfaces. Or you can use the codeless visual approach to build a new custom theme. Grouping - RadGridView allows easy implementation of multilevel grouping of data from a single table. Simply drag the column header(s) to the group panel on the top to define the grouping order and hierarchy. You can also programmatically group data using group-by expressions. Another unique feature is the ability to sort grouped data by single or multiple columns. Grouping programmatically also allows you to perform aggregate operations (e.g. sum, min, max, count, first and last) and to output custom formatted strings into the group heading. Multi-column sorting - in addition to the simple one-column sorting RadGridView allows you to sort data by several columns just like in Microsoft Excel. With the help of sorting expressions, you can also do custom sorting. Filtering - RadGridView can perform filtering operations for all columns that support filtering. For each column there will be a drop down menu with the available filter expressions Column and Row resizing - RadGridView supports convenient column and row resizing with features like real-time resizing, best fit sizing,automatic resizing of grid rows based on their content, and text wrapping. Column reordering with drag-and-drop - column reordering is a nice interface feature which lets users reorder columns, based on their personal preference. Telerik RadGridView allows users to quickly reorder columns at runtime by simply drag-and-dropping their headers, with visual indication of the header being dragged. Keyboard navigation - RadGridView can be navigated using the keyboard. You can focus on a grid with the TAB key, navigate through the rows, and edit cells. Rich set of column types - RadGridView supports the most commonly used column types to provide editing functionality. Pinned rows and Pinned columns support - RadGridView enhances the simple scrolling by supporting pinned rows and columns. You can scroll the grid data, while pinned rows stay visible and next to the header row; pinned columns stay visible and on the left of the grid. Conditional formatting - RadGridView enables you to apply conditional formatting to grid elements for enhanced readability and usability of the displayed data. Conditional formatting can be applied programmatically or by the user at run-time. Context menu support - The context menu provides extra usability and richness to any application. The default RadGridView context menu provides support for sorting, formatting, grouping, column selection and automatic column width adjustment. You can extend the context menu to add your own menu items and display your menus conditionally. Saving and loading layout functionality
558
Show/hide columns with the Column Chooser, resize, rearrange columns, pin/unpin Group-by column(s), filter, sort Conditional formatting
Using the Property Builder you can make changes quickly and get instant visual feedback. Using the "Advanced Settings" tab Properties Grid you can "fine tune" your settings. For example you can resize columns in the Property Builder, but if you wish your column to be exactly 250px wide you can use the Advanced SettingsProperties Grid, or the standard Visual Studio Properties window. 9. Press Ctl-F5 to run the projectandview the data in the RadGridView.
559
560
9. Close the Property Builder. 10. Add annamespacereference to the code-behind of the form. [VB] Adding Namespace Reference Imports Telerik.WinControls.UI [C#] Adding Namespace Reference using Telerik.WinControls.UI; 11. Add the code below to the Load method of the form. Notice that the "PercentQuota" expression is assigned in code. Then a new column is created completely from scratch and added to the columns collection. This code programmatically creates a CheckBox column which shows if a salesperson has reached over 15% of their sales quota for the year. Then column formats are set and finally the GridViewTemplate BestFitColumns() method is called. BestFitColumns calculates the best fit for each column based on the header text and data width so that neither header nor data is obscured. [VB] Handling the Form Load Event Private Sub RadGridViewLab2_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load ' load the dataset Me.salesPersonTableAdapter.Fill(Me.adventureWorksDataSet.SalesPerson) ' assign the "PercentQuota" expression, and set format to be a percentage Me.radGridView1.Columns("PercentQuota").Expression = "SalesYTD/SalesQuota" Me.radGridView1.Columns("PercentQuota").FormatString = "{0:P}" ' create a new "Over 15 Percent" checkbox Dim checkboxColumn As GridViewCheckBoxColumn = New GridViewCheckBoxColumn() checkboxColumn.Name = "CheckBoxColumn" checkboxColumn.HeaderText = "Over 15%" checkboxColumn.Width = 60 radGridView1.Columns.Add(checkboxColumn) checkboxColumn.Expression = "PercentQuota > 15" ' set column formats
561
562
The user can then drag column headings to the Column Chooser window.
563
The columns that are allowed to be visible in the Column Chooser can be configured at runtime. To prevent the column from being shown in the chooser, set the column's VisibleInColumnChooser property to false. If you want to prevent the column from being dragged off the grid, set the AllowHide property to false. Gotcha! If VisibleInColumnChooser is set to False and AllowHide is true, the column will disappear when dragged onto the column chooser and the user will not be able to restore the column to the grid. [VB] Disallowing a Column Dragging to Chooser Private Sub Form1_Load(sender As Object, e As EventArgs) Me.productTableAdapter.Fill(Me.adventureWorksDataSet.Product) radGridView1.Columns(1).VisibleInColumnChooser = False radGridView1.Columns(1).AllowHide = False End Sub [C#] Disallowing a Column Dragging to Chooser private void Form1_Load(object sender, EventArgs e) { this.productTableAdapter.Fill(this.adventureWorksDataSet.Product); radGridView1.Columns[1].VisibleInColumnChooser = false; radGridView1.Columns[1].AllowHide = false; } You can disable the chooser all together for any grid view template by setting the AllowColumnChooser property. This removes the column chooser from thegrid's context menu. [VB] Disabling the Column Chooser radGridView1.MasterTemplate.AllowColumnChooser = False [C#] Disabling the Column Chooser radGridView1.MasterTemplate.AllowColumnChooser = false; Alternatively, you can display the chooser programmatically using the ColumnChooser Show() method. [VB] Displaying the ColumnChooser radGridView1.ColumnChooser.Show() [C#] Displaying the ColumnChooser radGridView1.ColumnChooser.Show();
564
565
You can show the dialog programmatically by creating a ConditionalFormattingForm instance and calling the Show() method. The first parameter in the constructor takes the GridViewTemplate to apply formatting against. The second can be a GridViewDataColumn that the rule will apply to, or this can be left null. You can find the complete source for this project at: \Grid\<VB|CS>\RadGridView\ConditionalFormatting This example requires that you have pre installed AdventureWorks data base on your SQL server. You can download all AdventureWorks data bases from this link at CodePlex (http://msftdbprodsamples.codeplex.com/releases/view/55926) [VB] Showing the Conditional Formatting Dialog Private Sub btnShowDialog_Click(sender As Object, e As EventArgs) Dim cf As New ConditionalFormattingForm(radGridView1.MasterTemplate, Nothing) cf.Show() End Sub [C#] Showing the Conditional Formatting Dialog private void btnShowDialog_Click(object sender, EventArgs e) { ConditionalFormattingForm cf = new ConditionalFormattingForm(radGridView1.MasterTemplate, null); cf.Show(); } In fact, you can remove or replace items in the grid's context menu with your own items. The example below swaps out the "Conditional Formatting" item with a "My Conditional Formatting" item that displays the conditional formatting dialog as always topmost. [VB] Replacing Grid Context Menu Items
566
567
[VB] Adding Rules Programmatically ' create a rule to highlight "SuperiorCard" card types ' -highlight the entire row Dim cfo As New ConditionalFormattingObject("SuperiorCards", ConditionTypes.Equal, "SuperiorCard", "", True) cfo.RowBackColor = Color.LightGreen cfo.RowForeColor = Color.DarkGreen cfo.TextAlignment = ContentAlignment.MiddleRight radGridView1.Columns("CardType").ConditionalFormattingObjectList.Add(cfo) ' hightlight cards with expiry year less than 2008. ' -highlight only the cell Dim cfo2 As New ConditionalFormattingObject("Expired Cards", ConditionTypes.Less, "2008", "", False) cfo2.CellBackColor = Color.Transparent cfo2.CellForeColor = Color.Red cfo2.TextAlignment = ContentAlignment.MiddleRight radGridView1.Columns("ExpYear").ConditionalFormattingObjectList.Add(cfo2) [C#] Adding Rules Programmatically // create a rule to highlight "SuperiorCard" card types // -highlight the entire row ConditionalFormattingObject cfo = new ConditionalFormattingObject("SuperiorCards", ConditionTypes.Equal, "SuperiorCard", "", true); cfo.RowBackColor = Color.LightGreen; cfo.RowForeColor = Color.DarkGreen; cfo.TextAlignment = ContentAlignment.MiddleRight; radGridView1.Columns["CardType"].ConditionalFormattingObjectList.Add(cfo); // hightlight cards with expiry year less than 2008. // -highlight only the cell ConditionalFormattingObject cfo2 = new ConditionalFormattingObject("Expired Cards", ConditionTypes.Less, "2008", "", false); cfo2.CellBackColor = Color.Transparent; cfo2.CellForeColor = Color.Red;
568
The conditions are too complex. You want to format other than just cell and row colors and alignment. You need to compare values in other cells as part of evaluating the condition. You need special effects like alternate row colors.
...then the CellFormatting and RowFormatting events provide complete control over any visual aspect of the cell element and allows you toconstruct arbitrarily complex evaluations using any programmatic tool in the .NET arsenal. RowFormating and CellFormating events fireevery timea visible row or cell is created. Even though you can create complex code in these event handlers, have a care for performance as these events will fire for all visible rows or cells. The events are fired in the following order:
The RowFormatting event is called after applying all theme properties and updating row elements state. The CellFormatting event is fired for every cell in the row. To be more effective and to save memory, RadGridView uses virtualization of its elements. This means that a limited number of elements are created at a time. Only the rows that are currently visible on the screen have associated visual elements. When the grid is scrolled up the visual elements are reused. The formatting events are fired only for rows that have associated visual elements.
Cell Formatting The example below makes extensive visual changes to the cell element based on the current column's data (CardType = "SuperiorCard") and another column (ExpYear < 2008). The example first tests that the column is a GridViewDataColumn type. This lets us get the GridViewDataColumnName so we can know what column we're on. Use CellElement.RowInfo.Cells ["MyColumnName"] to get at other columns. Another important point is that if you want to changethe BackColor properties of the CellElement, you should set the DrawFill property to True. Gotcha! Be sure to set DrawFill back to false whenever you're not specifically accessing the BackColor. Forgetting to do this will cause anomalous painting of other cells in the column as you scroll. You should always reset the modified properties when a condition is not met. In short, you should always have an "else" clause for every "if" clause. You can find the complete source for this project at: \Grid\<VB|CS>\RadGridView\RowCellFormatting This example requires that you have pre installed AdventureWorks data base on your SQL server. You can download all AdventureWorks data bases from this link at CodePlex (http://msftdbprodsamples.codeplex.com/releases/view/55926)
569
[VB] Handling the CellFormatting Event Private Sub radGridView1_CellFormatting(ByVal sender As Object, ByVal e As CellFormattingEventArgs) Handles radGridView1.CellFormatting ' make sure the column is not the header and is a GridViewDataColumn If TypeOf e.CellElement.ColumnInfo Is GridViewDataColumn AndAlso Not(TypeOf e.CellElement Is GridHeaderCellElement) Then Dim column As GridViewDataColumn = TryCast(e.CellElement.ColumnInfo, GridViewDataColumn) ' only make changes to the CardType column If column.Name.Equals("CardType") AndAlso e.CellElement.RowInfo.Cells("ExpYear").Value IsNot Nothing Then ' get value of the "ExpYear" Dim year As Integer = CShort(Fix(e.CellElement.RowInfo.Cells("ExpYear").Value)) ' make changes based on another column ("ExpYear") where the current ' column contains "SuperiorCard" If (year < 2008) AndAlso (e.CellElement.Text.Equals("SuperiorCard")) Then ' must set DrawFill for background colors to show! e.CellElement.DrawFill = True ' change any CellElement property e.CellElement.BackColor = Color.PaleGreen e.CellElement.BackColor2 = Color.LightGreen e.CellElement.BackColor3 = Color.YellowGreen e.CellElement.BackColor4 = Color.Green e.CellElement.NumberOfColors = 4 e.CellElement.GradientStyle = GradientStyles.OfficeGlassRect Else ' must reset the visual modifications e.CellElement.ResetValue(LightVisualElement.DrawFillProperty, ValueResetFlags.Local) e.CellElement.ResetValue(LightVisualElement.BackColorProperty, ValueResetFlags.Local) e.CellElement.ResetValue(LightVisualElement.BackColor2Property, ValueResetFlags.Local) e.CellElement.ResetValue(LightVisualElement.BackColor3Property, ValueResetFlags.Local) e.CellElement.ResetValue(LightVisualElement.BackColor4Property, ValueResetFlags.Local) e.CellElement.ResetValue(LightVisualElement.NumberOfColorsProperty, ValueResetFlags.Local) e.CellElement.ResetValue(LightVisualElement.GradientStyleProperty, ValueResetFlags.Local) End If
570
571
[VB] Handling the RowFormatting Event Private Sub radGridView1_RowFormatting(ByVal sender As Object, ByVal e As RowFormattingEventArgs) Handles radGridView1.RowFormatting If toggleButtonEnableAlternationRowColor.ToggleState = ToggleState.On Then If e.RowElement.IsOdd Then e.RowElement.DrawFill = True e.RowElement.BackColor = Color.LightGreen e.RowElement.BackColor2 = Color.PaleTurquoise e.RowElement.BackColor3 = Color.PaleGreen e.RowElement.BackColor4 = Color.SpringGreen e.RowElement.GradientStyle = GradientStyles.Vista Else e.RowElement.ResetValue(LightVisualElement.BackColorProperty, ValueResetFlags.Local) e.RowElement.ResetValue(LightVisualElement.BackColor2Property, ValueResetFlags.Local) e.RowElement.ResetValue(LightVisualElement.BackColor3Property, ValueResetFlags.Local) e.RowElement.ResetValue(LightVisualElement.BackColor4Property, ValueResetFlags.Local) e.RowElement.ResetValue(LightVisualElement.GradientStyleProperty, ValueResetFlags.Local) e.RowElement.ResetValue(LightVisualElement.DrawFillProperty, ValueResetFlags.Local) End If End If End Sub [C#] Handling the RowFormatting Event private void radGridView1_RowFormatting(object sender, RowFormattingEventArgs e) { if (toggleButtonEnableAlternationRowColor.ToggleState == ToggleState.On) { if (e.RowElement.IsOdd) { e.RowElement.DrawFill = true; e.RowElement.BackColor = Color.LightGreen; e.RowElement.BackColor2 = Color.PaleTurquoise; e.RowElement.BackColor3 = Color.PaleGreen; e.RowElement.BackColor4 = Color.SpringGreen;
572
573
SetContentCore(object value): To set the cell text. SetContent(): To create or modify any cell content. ArrangeOverride(SizeF finalSize): To handle layout requirements specific to your cell type. ThemeEffectiveType - to make the element themable IsCompatible - defines with which column types the cell is compatible with
The example below uses the "Color" column from the Products table and creates a special ColorSwatchCellElement custom cell type. Clicking on the cell displays the color dialog and lets the user change colors.
574
Defining a Custom Cell Type You can find the complete source for this project at: \Grid\<VB|CS>\RadGridView\CustomCells 1. In a new WinForms application, drop a RadGridView on the default form and set the Dock property to "Fill". 2. Bind the AdventureWorks "Products" table to the grid and include only the "ProductID", "Name" and "Color" columns. 3. First create a new class "ColorSwatchElement.cs". Change the declaration of the class to be public, descend from GridDataCellElement and add a constructor that takes a GridViewColumn and GridRowElement as parameters. [VB] Initial ColorSwatchCellElement Definition Public Class ColorSwatchCellElement Inherits GridDataCellElement Public Sub New(column As GridViewColumn, row As GridRowElement) MyBase.New(column, row) End Sub End Class [C#] Initial ColorSwatchCellElement Definition public class ColorSwatchCellElement : GridDataCellElement { public ColorSwatchCellElement(GridViewColumn column, GridRowElement row) : base(column, row) { } } 4. Add a new private member "_swatch" and make it a LightVisualElement type. Then override the CreateChildElements() method and create an instance of the LightVisualElement and set properties before adding to the Children collection:
575
Shape = new RoundRectShape with a 5 point radius GradientStyle = "Linear" NumberOfColors = 2 MouseDown = Remove and assign a new MouseDown event handler [VB]Overiding the CreateChildElements Method Private _swatch As LightVisualElement Protected Overloads Overrides Sub CreateChildElements() MyBase.CreateChildElements() _swatch = New LightVisualElement() _swatch.DrawFill = True _swatch.Font = New Font("Arial", 7F, FontStyle.Regular) _swatch.Shape = New RoundRectShape(5) _swatch.GradientStyle = GradientStyles.Linear _swatch.NumberOfColors = 2 RemoveHandler _swatch.MouseDown, AddressOf _swatch_MouseDown _swatch.MouseDown += New MouseEventHandler(_swatch_MouseDown) Me.Children.Add(_swatch) End Sub [C#]Overiding the CreateChildElements Method private LightVisualElement _swatch; protected override void CreateChildElements() { base.CreateChildElements(); _swatch = new LightVisualElement(); _swatch.DrawFill = true; _swatch.Font = new Font("Arial", 7F, FontStyle.Regular); _swatch.Shape = new RoundRectShape(5); _swatch.GradientStyle = GradientStyles.Linear; _swatch.NumberOfColors = 2; _swatch.MouseDown -= new MouseEventHandler(_swatch_MouseDown); _swatch.MouseDown += new MouseEventHandler(_swatch_MouseDown); this.Children.Add(_swatch); }
5. Override the ArrangeOverride method in order to size the element according to the cell size [VB.NET]Overriding ArrangeOverride Protected Overrides Function ArrangeOverride(finalSize As SizeF) As SizeF MyBase.ArrangeOverride(finalSize) 'size the element according to the cell size _swatch.Arrange(New RectangleF(3, 3, finalSize.Width - 6, finalSize.Height - 6)) Return finalSize End Function [C#] Overriding ArrangeOverride protected override SizeF ArrangeOverride(SizeF finalSize) { base.ArrangeOverride(finalSize); //size the element according to the cell size _swatch.Arrange(new RectangleF(3, 3, finalSize.Width - 6, finalSize.Height - 6)); return finalSize; }
576
577
578
579
580
Grouping
581
5. Now, you can expand a Country group to view the data in that group. Also, the order of the grouping can be changed by clickingthe group header in the Grouping Panel.
582
6. To add an additional subgroup by City, drag the City column header to the right-hand side of the Country grouping block.
583
The hierarchy of the grouping can be re-arranged by changing the header blocks within the Grouping Panel. To Ungroup by a column, simply drag the column header back to the header row or use the close button in the group header.
584
3. In the Collection Editor, add a new GroupDescriptor and set the Expression property to: Country DESC 4. Add a second GroupDescriptor and set its Expression to City ASC
585
5. Click OK to close the Collection Editor 6. Click OK to close the Property Builder. You should now see your new groupings in the Grouping Panel in design view, just as earlier when they were created by the user at run-time. 7. Run the project to view the grouped data, this time in descending order for country, and ascending for city. Although the groupings set up in the designer will be applied on start-up, at runtime, the user can still drag the grouped header to re-arrange, add, or delete groupings from the grid, as long as the EnableGrouping property is set to True.
586
587
588
7. Add namespace referencesto the"Imports" (VB) or "uses" (C#) clause of your code: [VB] Adding References Imports Telerik.WinControls.UI Imports Telerik.WinControls.Data [C#] Adding References using Telerik.WinControls.UI; using Telerik.WinControls.Data; 8. To add an additional expression to sort by Color programmatically, close the Property Builder and add the following code to the Load handler of the form: [VB] Adding a Sort Descriptor radGridView1.MasterTemplate.SortDescriptors.Add(new SortDescriptor("Color", System.ComponentModel.ListSortDirection.Ascending)) [C#] Adding a Sort Descriptor radGridView1.MasterTemplate.SortDescriptors.Add(new SortDescriptor("Color", System.ComponentModel.ListSortDirection.Ascending)); 9. Run the project to view your sorted data. Notice that the data is first sorted by Reorder Point, then within that sorting, is sorted by Color.
589
If EnableSorting is set to true, users will still be able to change your default sorting at runtime using the column headers. Setting EnableSorting to false freezes the sort order to the configuration set at either design time or programmatically. 10. To add run-time filtering to the table, click the filter icon on the Reorder Point column, and choose "Greater than" from the context menu. Now enter "300" into the filter row textbox to only show products with a Reorder Point greater than 300.
You can click the filter iconand choose "No filter" to remove the filtering criteria. 11. Stop the project and return to the Forms Load handler. Now programmatically add a filtering descriptor to
590
A FilterOperator enumeration member that represent one of the filtering criteria in the drop down list, e.g. "GreaterThan", "EqualTo", etc. A criteria value, i.e. the value that the column value is being compared to. In the example below the value is "True". [VB] Adding a Filter Expression radGridView1.MasterTemplate.FilterDescriptors.Add(new FilterDescriptor("MakeFlag", FilterOperator.IsEqualTo, true)) [C#] Adding a Filter Expression radGridView1.MasterTemplate.FilterDescriptors.Add(new FilterDescriptor("MakeFlag", FilterOperator.IsEqualTo, true));
12. To additionally filter results to only those with ProductNumbers starting with the letters "C" or "R" you should use CompositeFilterDescriptors. Here we will create a composite filter descriptor which will contain two filter descriptors in it - to filter the results by ProductNumbe starting with "C" and starting with "R". To have both or them working, the LogicalOperator of the CompositeFilterDescriptor instance should be set to "OR". After the composite descriptor is created, we are adding it to the filter descriptor collection of the MasterTemplates (where the descriptor for the MakeFlag column is already added): [VB] Creating CompositeFilterDescriptor Dim compositeDescriptor As New CompositeFilterDescriptor() compositeDescriptor.LogicalOperator = FilterLogicalOperator.[Or] compositeDescriptor.FilterDescriptors.Add(New FilterDescriptor("ProductNumber", FilterOperator.StartsWith, "C")) compositeDescriptor.FilterDescriptors.Add(New FilterDescriptor("ProductNumber", FilterOperator.StartsWith, "R")) radGridView1.MasterTemplate.FilterDescriptors.Add(compositeDescriptor) [C#] Creating CompositeFilterDescriptor CompositeFilterDescriptor compositeDescriptor = new CompositeFilterDescriptor(); compositeDescriptor.LogicalOperator = FilterLogicalOperator.Or; compositeDescriptor.FilterDescriptors.Add(new FilterDescriptor("ProductNumber", FilterOperator.StartsWith, "C")); compositeDescriptor.FilterDescriptors.Add(new FilterDescriptor("ProductNumber", FilterOperator.StartsWith, "R")); radGridView1.MasterTemplate.FilterDescriptors.Add(compositeDescriptor); 13. Run the project and notice the effect of our filter expressions. Only Products with "True" MakeFlags whose number starts with "C" or "R" are shown.
591
There is a more convenient way to sort a column.Instead of adding a new SortDescriptor, set the SortOrder property: [VB] Assigning the SortOrder Me.radGridView1.Columns("Value").SortOrder = RadSortOrder.Descending [C#] Assigning the SortOrder this.radGridView1.Columns["Value"].SortOrder = RadSortOrder.Descending;
21.10Hierarchy Support
ith some data, it is desirable to show tables within tables, also known as a Hierarchical view. Multiple tables can be related through data keys and RadGridView allows almost effortless setup to display such relationships. Hierarchical tables can be set up through either the designer manually, automatically, or programmatically in the code-behind. The following labs will demonstrate all implementation methods. Additionally, Objectrelational hierarchy, Self-referencing hierarchyand Load on demand hierarchy will be reviewed.
592
3. Again using the Smart Tag, select the Department Table as the source for the main grid.
593
4. Now, open the Property Builder for the grid. Select theMasterTemplate node, and then expand the New drop down button and click ChildTemplate.
5. After the template is added,select it and navigate to the Data pane.Locate the DataSource property andfrom the drop down menu select the EmployeeDepartmentHistory table. This will be the child table within the grid. Afterwards, click OK to save the Templates collection.
594
6. Select the RadGridView node andopen the Collections editor for the Relations collection.
595
7. In the GridViewRelation Collection Editor, add a new relation by clicking the "Add" button. Then, name your relation in the properties pane on the right side of the Collection Editor. Here, the relation is named "DepartmenttoDepartmentHistory". Set the templates of the relation to your newly created Child template for the ChildTemplate property, and theMasterTemplate for the ParentTemplate.
8. Finally, set the related column by adding the Column Name DepartmentID to the collections of the
596
9. Run the project and view the hierarchical tables in the form:
Notice that the Main Grid shows the data from the Departments database table, and by clicking the plus sign to the left of a Department record, you can view the Child table, which displays the Employees who have the same DepartmentID in the EmployeeDepartmentHistory table.
597
3. Use the Smart Tag to set the DataSource property to the DataSet itself. This will give RadGridView access to both tables and the relationship between them.
598
4. To view the relationships that are automatically created in the new Dataset, close the Property Builder and use the SmartTag on the Dataset object placeholder in the Forms design panel to choose "Edit in DataSet Designer".
5. In the DataSet Designer, notice that the two tables are linked by a relationship line. The relationship between the tables is the VendorID field, which is the Primary Key for the Vendor table, and a Foreign Key for the ProductVendor table. This relationship will be the basis for our auto-generated hierarchical table view.
599
Notice that the table of Vendors is the parent table, and by expanding a Vendor Record, we can view a child table displaying the Products associated with that Vendor from the ProductsVendor table.
600
601
602
603
Object-relational hierarchy
The Object-Relational Hierarchy mode is used to show hierarchy based on a complex IList (IEnumarable) object that contains inner ILits (IEnumerable) properties. In order to create an Object-Relational Hierarchy automatically in this scenario, you must set only the DataSource and the AutoGenerateHierarachy properties of RadGridView. You can find the complete source for this project at: \Grid\<VB|CS>\RadGridView\ObjectRelationalHierarchy In the final lab on hierarchical tables, we will construct the hierarchy programmatically in the codebehind for the form itself. 1. Create a new Windows Forms Project. 2. Drag a RadGridView control onto the form. 3. Right click the project file and select Add > New Item. 4. Select ADO.NET Entity Data Model and change the Name to NorthwindEntities and click Add.
604
605
606
7. Type your server name, select the Northwind database and click OK.
607
608
9. Expand the tables node and select the Products and Suppliers tables.
609
10. The entity model will be generated. It will look like this.
610
11. Double click the form to create Load event handler. Create an instance of the NorthwindEntities, create a query that will get the suppliers and include the Products table. Set the grid DataSource to the query to list and set the AutoGenerateHierarchy to true. [VB.NET] Object-relational hierarchy Dim entities As New NorthwindEntities() Dim query = From suppliers In entities.Suppliers.Include("Products") Select suppliers Me.RadGridView1.DataSource = query.ToList() Me.RadGridView1.AutoGenerateHierarchy = True [C#] Object-relational hierarchy NorthwindEntities entities = new NorthwindEntities(); var query = from suppliers in entities.Suppliers.Include("Products") select suppliers; this.radGridView1.DataSource = query.ToList(); this.radGridView1.AutoGenerateHierarchy = true; 12. Run the project to view the created hierarchy
611
Load-On-Demandhierarchy
In many cases you may need to load your data not when RadGridView is being initialized, but at a later moment, when you interact with RadGridView or with your application. For example, a child template can be loaded on demand to delay the initialization of a resource-demanding feature of the application until it is required. In order to load a GridViewTemplate on demand, you should follow these high-level steps:
Create and define a columns schema for the presented data at the first level of the hierarchy. Create and define a columns schema for the presented data and a child GridViewTemplate. Create and associate a GridViewEventDataProvider with the child GridViewTemplate. Handle the RowSourceNeeded event to populate the data for each parent row.
You can find the complete source for this project at: \Grid\<VB|CS>\RadGridView\HierarchyLoadOnDemand 1. Create a new Windows Forms Project. 2. Drag a RadGridView control onto the form, and use the Smart Tag to create a new DataSource. Use the AdventureWorks database, and select both the Product and ProductModel tables. 3. Again using the Smart Tag, first select the Product, then the ProductModel tables to create the table adapters and then set the grid datasource to None, since we are going to assisgn the data source in the code behind.
612
4. Double click the created AdventureWorksDataSet. Right click the designer and select Add > Relation
613
5. Set the Parent Table to Product and the Child Table to ProduceModel. Both column settings should point to ProductModelID.
614
6. First, create a columns schema for the first (parent) level of the hierarchy. If RadGridView is in a databound mode and we do not need to set a custom schema, we can just set the DataSource property of RadGridView which will set the schema and will populate the parent level with data. [VB.NET] Defining the child template Private Function CreateChildTemplate() As GridViewTemplate Dim template As New GridViewTemplate() template.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill Dim namecolumn As New GridViewTextBoxColumn("Name") Dim productNumberColumn As New GridViewTextBoxColumn("ProductNumber") Dim colorColumn As New GridViewTextBoxColumn("Color") Dim listPriceColumn As New GridViewDecimalColumn("ListPrice") Dim sizeColumn As New GridViewTextBoxColumn("Size") Dim weightColumn As New GridViewDecimalColumn("Weight") Dim discontinuedColumn As New GridViewDateTimeColumn("DiscontinuedDate") template.Columns.AddRange(namecolumn, productNumberColumn, colorColumn, listPriceColumn,
615
Me.radGridView1.DataSource = productModelBindingSource; Dim childTemplate As GridViewTemplate = CreateChildTemplate() Me.RadGridView1.Templates.Add(childTemplate) childTemplate.HierarchyDataProvider = New GridViewEventDataProvider(childTemplate) AddHandler RadGridView1.RowSourceNeeded, AddressOf radGridView1_RowSourceNeeded End Sub Example Title void Form1_Load(object sender, EventArgs e) { this.productModelTableAdapter.Fill(this.adventureLT2008DataSet.ProductModel); this.productTableAdapter.Fill(this.adventureLT2008DataSet.Product);
616
617
This new event based hierarchy mode can be used in different lazy loading scenarios including ORM frameworks, WCF services or complex business objects.
Self-referencinghierarchy
Except displaying hierarchical data and applying some custom criteria about when the subset of data to be displayed, the RadGridView allows you to define a relation that points back to the same table. In the cases when the hierarchical data is build from one type of items you can use a self referencing RadGridView to display the data. The following example demonstrates how RadGridView displays a hierarchy based on the data provided by the file system where one folder can have files and folders that can have other files and folders, etc.
618
You can find the complete source for this project at: \Grid\<VB|CS>\RadGridView\HierarchySelfReferencing 1. Create a new Windows Forms Project. 2. Drag a RadGridView control onto the form, and set its Dock property toi "Fill". 3. Create a datasource with an appropriate structure where each data record contains Id that serves as a unique identifier for the record and ParentId that determines the parent of the data record. In our case this is a business object of type FileSystemItem that can serve as a folder and as a document. [VB.NET] Create data source structure Public Class FileSystemItem Private id_Renamed As Integer Private name_Renamed As String Private creationTime_Renamed As Date Private parentFolderId_Renamed As Integer Private type As String Public Property Id() As Integer Get Return id_Renamed End Get Set(ByVal value As Integer) id_Renamed = value End Set End Property
619
620
621
622
623
624
21.11Virtual Mode
"Virtual Mode" provides a way to explicitly implement the data management of your RadGridView control. This is especially useful when binding to large groups of data, because it can let you only load the data currently being used, thus improving the performance of the grid. Virtual mode is also necessary when bound and unbound columns are used together, but sorted by the bound columns values. In the following simplistic example of Virtual Mode, the RadGridView receives its data by calling the CellValueNeeded event handler. To allow us to see the updates, we will use a table of constantly changing randomly selected employee records as the RadGridViews contents. You can find the complete source for this project at: \Grid\<VB|CS>\RadGridView\VirtualMode This example requires that you have pre installed AdventureWorks data base on your SQL server. You can download all AdventureWorks data bases from this link at CodePlex (http://msftdbprodsamples.codeplex.com/releases/view/55926) 1. Create a new Windows Forms Project. 2. Drag a RadGridView control onto the form, as well as a Timer object that will be used to control our data updates. Set the Timer Interval property to "100". 3. We will be doing all the setup for the RadGridView control itself programmatically, but first we still have to create a Dataset in our project to connect. Again, use the RadGridViews Smart Tag to create a new project DataSource. 4. Use the AdventureWorks database, and select the Person.Contact table only. We will again be using the default name AdventureWorksDataSet. Note: After creating the Dataset, be sure to leave the RadGridViews DataSource set to "none", as we will be using Virtual Mode to provide the data contents. Notice that now you have an adventureWorksDataSet object, along with a corresponding Binding Source and Table Adapter in the component tray. The Timer component will also appear in the tray.
625
Code to populate the DataSet using the Table Adapteris automatically placed in the Forms Load handler. Do not remove this code! 5. Add the following declarations to the Form class, directly above the constructor method. These lines declare the numbers of columns and rows for our data, along with the List of string Lists that will hold the current data. [VB] Declaring Private Variables Private ContactTable As New List(Of List(Of String))() Private NumberOfRows As Integer = 20 Private NumberOfCols As Integer = 4 [C#] Declaring Private Variables private List<List<string>> ContactTable = new List<List<string>>(); private int NumberOfRows = 20; private int NumberOfCols = 4; 6. We also need to create a method which will update the data in our ContactTable. Add the following method to the Forms class. This method uses the current times tick value as the seed to generate a new random number from 0 to 1000; then uses that index value to pull a Contact record from the dataset and add it to the table. The method will be called each time our Timer objects Tick event is triggered. [VB] Refresh the Contact Table Private Sub RefreshContactData() Dim random As New Random(DirectCast(DateTime.Now.Ticks, Integer)) Dim i As Integer = 0 While i < NumberOfRows Dim index As Integer = random.[Next](1000) Dim cr As AdventureWorksDataSet.ContactRow = adventureWorksDataSet.Contact(index) ContactTable(i)(0) = cr.FirstName ContactTable(i)(1) = cr.LastName ContactTable(i)(2) = cr.EmailAddress ContactTable(i)(3) = cr.Phone System.Math.Max(System.Threading.Interlocked.Increment(i),i - 1) End While End Sub [C#] Refresh the Contact Table private void RefreshContactData() { Random random = new Random((int)DateTime.Now.Ticks); for (int i = 0; i < NumberOfRows; i++) { int index = random.Next(1000); AdventureWorksDataSet.ContactRow cr = adventureWorksDataSet.Contact[index]; ContactTable[i][0] = cr.FirstName; ContactTable[i][1] = cr.LastName;
626
627
628
629
630
4. Next we will add the data connection to our LINQ to SQL class. While in the design view for the SalesOrderHeaderDataClass, expand the Server Explorer window of Visual Studio to the Sales.SalesOrderHeader table of the AdventureWorks database. You may need to open a connection to the database to view the tables. Then, drag the SalesOrderHeader table onto the design surface to add the table to the class.
Remove all but the following fields from the Table object: SalesOrderID, OrderDate, SubTotal, TaxAmt, Freight, and TotalDue. 5. Now, to set up the user interface of our example, drag a RadGridView control onto the Form, and set the
631
6. Also drag onto the Form the following controls: two ComboBoxes, a NumberUpDown control, a Button, and two Labels. Arrange the controls similar to the layout shown below, and name the controls as follows, from left to right: cbField, cbSortType, btnSort, and numRecords.
632
7. To populate the Field combobox, use the Smart Tag to open the Items list editor, and add the following Fields:
633
9. To add a Click event handler for the Button control, double click the button in design view, and add the following code to the new event handler: [VB] Loading Data Via LINQ Private Sub btnSort_Click(ByVal sender As Object, ByVal e As EventArgs) Me.radGridView1.TableElement.BeginUpdate() Dim queryable As IQueryable = New SalesOrderHeaderDataClassDataContext ().SalesOrderHeaders.AsQueryable() queryable = queryable.OrderBy([String].Format("{0} {1}", cbField.Text, cbSortType.Text)) radGridView1.DataSource = queryable.Take(Convert.ToInt32(numRecords.Value)) Me.radGridView1.TableElement.EndUpdate(True) End Sub [C#] Loading Data Via LINQ private void btnSort_Click(object sender, EventArgs e) { this.radGridView1.TableElement.BeginUpdate(); IQueryable queryable = new SalesOrderHeaderDataClassDataContext ().SalesOrderHeaders.AsQueryable(); queryable = queryable.OrderBy(String.Format("{0} {1}", cbField.Text, cbSortType.Text)); radGridView1.DataSource = queryable.Take(Convert.ToInt32(numRecords.Value)); this.radGridView1.TableElement.EndUpdate(true); } This code temporarily disables updating on the grid, then assembles the new query from the options selected by the user, and uses the query to retrieve data from the table using the LINQ to SQL data class. 10. Adda reference toSystem.Linq.Dynamic in the "Imports" (VB) or "uses" (C#) section of the code. 11. Run the project to view the form. Select a Field and Sort direction from the comboboxes, and set the number of records to return. Click the Sort button to view the results, which are retrieved from the database using the dynamic query.
634
Even though the actual data table is over 30,000 records, the grid is only loading the values retrieved by the query, and so maintains high performance even with very large record sets. This same technique can be used to implement custom paging and filtering on the RadGridView control.
21.13Expression Editor
RadExpressionEditor is a powerful editor that allows you to build complex expressions using a simple Domain Specific Language, reminiscent of formulas in many popular spreadsheet applications. It provides easy access to a set of predefined functions, operators, constants. You can also access all RadGridView fields. Expressions consist of functions, operators, constants, and identifiers (for example, the names of fields, tables, forms, and queries). The Expression Builder enables you to easily look up and insert these components, and thereby enter expressions more quickly and accurately. Expression editor can be started from the context menu of the particular column, or it can be initialized and shown from code. RadExpressionEditor also can be used in design time. Once shown, RadExpressionEditor automatically loads all available functions, operators and current grids fields (columns). In addition, every entered expression is parsed and evaluated. A preview of the result is shown (for the current row of the grid) and the confirmation button is enabled only if there is a valid expression. Please note that the preview is shown only if there is at least one row at run time.
635
Anatomy of RadExpressionEditor
636
1. Expression Box. Type your expression here, or add expression elements by double-clicking or dragging items in the element lists below; 2. Common Expression Operators. Use buttons as fast shortcuts to add the required operator; 3. Expression Elements Tree. Navigate through the available categories of expression elements; 4. Expression Values List. Scroll through the available expression functions, operators, constants or fields. Double-Click or drag-and-drop to add a chosen value into the expression box; 5. Help and information about the selected expression value. If available, here you will see the description and the syntax of the chosen expression value; 6. Result Preview. A preview of the calculated result of the entered expression will be shown. The preview is evaluated as you type, and is shown only if there is a valid expression. The result is calculated for the current row in the DataView.
Design-time
At design time you can open RadExpressionEditor by clicking the ellipsis button of the columns' Expressionproperty:
637
At design time the Result Preview functionality is not working, because there is no real data to evaluate. In addition, the expression is checked for validity. However, it cannot be verified according to actual data and value types. Because of this, it is possible to save an invalid expression at design time. If an invalid expression is created, an exception message will be shown when the project is ran.
638
639
End-user Support
End-users have two options for getting the RadExpressionEditor shown at run time:
[C#] GridViewTextBoxColumn col = new GridViewTextBoxColumn(); col.Name = "expression"; col.HeaderText = "My Expression"; col.Width = 150; col.EnableExpressionEditor = true; this.radGridView1.Columns.Add(col); [VB.NET]
640
DrawText = true Image = "" Text = Export Excel, Export PDF, Export HTML and Export CSV Name = btnExportExcel, btnExportPDF, btnExportHTML and btnExportCSV
3. Drag a RadGridView grid onto the form, and set the Dock property to "Fill". 4. Open the RadGridViews Smart Tag, and under "Choose DataSource" select "Add Project DataSource". 5. Use the DataSource wizard to set up a DataBase DataSource to the AdventureWorks database, and the Sales.SalesPerson table. Select all the columns in the table, and save the BindingSource to the project. The RadGridView should now be configured to show all of the columns in the table.
641
Exporting to Excel
This method offers excellent export performance and does not require MS Office installation on users' machines. The ExcelML format can be read from MS Excel 2002 (MS Office XP) and above. 1. In code view, navigate to btnExportExcel_Click event handler and create an instance of SaveFileDialog and the exporter. When instantiating the exporter pass in the parameters the RadGridView instance which you want to export. [VB.NET] Create an instance of Excel exporter Dim sfd As New SaveFileDialog() sfd.Filter = [String].Format("{0} (*{1})|*{1}", "Excel Files", ".xls") If sfd.ShowDialog() = DialogResult.OK Then 'create instance of the exporter Dim exporter As New ExportToExcelML(Me.RadGridView1) End If [C#] Create an instance of Excel exporter SaveFileDialog sfd = new SaveFileDialog(); sfd.Filter = String.Format("{0} (*{1})|*{1}", "Excel Files", ".xls"); if (sfd.ShowDialog() == DialogResult.OK)
642
FileExtension - defines the file extension for the exported file HiddenColumnOption and HiddenRowOption properties to determine how hidden rows and columns should behandled by theexporter. ExportVisualSettings property defines wether to export the visualsettings (themes) too. SheetMaxRows -RadGridView splits the data on separate sheets if the number of rows is greater than the Excel maximum. The maximum rows for Excel 2007 is 1048574 and for previous versions it is 65536 (which is the default setting) SheetName - sets the sheet name SummariesExportOption - defines how summary rows should be handled [VB.NET] Exporter settings 'define the file extension exporter.FileExtension = "xls" 'define what action should be taken for the hidden columns exporter.HiddenColumnOption = Telerik.WinControls.UI.Export.HiddenOption.DoNotExport 'should it export formatting exporter.ExportVisualSettings = True 'prevent exporting of summaries exporter.SummariesExportOption = SummariesOption.DoNotExport 'set the sheet max rows exporter.SheetMaxRows = ExcelMaxRows._1048576 'set the sheet name exporter.SheetName = "Sheet" [C#] Exporter settings //define the file extension (set this to xml if you want to prevent Excel warnings) exporter.FileExtension = "xls"; //define what action should be taken for the hidden columns exporter.HiddenColumnOption = Telerik.WinControls.UI.Export.HiddenOption.DoNotExport; //should it export formatting exporter.ExportVisualSettings = true; //prevent exporting of summaries exporter.SummariesExportOption = SummariesOption.DoNotExport; //set the sheet max rows exporter.SheetMaxRows = ExcelMaxRows._1048576; //set the sheet name exporter.SheetName = "Sheet";
3. The exporter offers also two events ExcelCellFormatting and ExcelTableCreated. The first one allows you to customize the appearance of each cell related to the exported RadGridView. The second one can be used with the AddCustomExcelRow method, which allows adding and formatting of new custom rows on the top of every sheet. Subscribe for this events in the button click event handler. The following code creates a custom row above the exported data and customizes that row appearance. Additionally, the cells in the SalesLastYear with value above 1 500 000 will bein yellow color. [VB.NET] Modify cell appearance and add custom row Sub exporter_ExcelTableCreated(ByVal sender As System.Object, ByVal e As Telerik.WinControls.UI.Export.ExcelML.ExcelTableCreatedEventArgs)
643
644
6. When the export is completed, a MessageBox will notify you. This is how the exported file will look like
645
Exporting to PDF
Export to PDF offers various rendering settings. RadGridView will be first rendered as an XHTML table and the export process will convert that table to a PDF document. That said, Export to PDF supports all of the ExportToHTML settings, but it also adds some PDF specific ones. Here is a list of the available properties:
FileExtension - defines the file extension for the exported file HiddenColumnOption and HiddenRowOption properties to determine how hidden rows and columns should behandled by theexporter. ExportVisualSettings property defines whether to export the visualsettings (themes) too. SummariesExportOption - defines how summary rows should be handled PageTitle - sets the page title for every page in the exported file. FitToPageWidth - fits the grid to the PDF page width Scale - changes the grid size TableBorderTickness - control the tickness of the table border PdfExportSettings - these property supports various settings on PDF file level:
646
EnableModify EnablePrinting FontType Keywords Page Margins: PageBottomMargin, PageTopMargin, PageLeftMargin, PageRightMargin, PageFooterMargin Page Size: PageHeight and PageWidth Producer Subject Title
HTMLCellFormatting event- since the export process first renders RadGridView data in XHTML you can use the event which comes from ExportToHTML class to make additional formatting on every cell related to the exported RadGridView
The export process follows the same logic. Create and instance of the ExportToPDF class and introduce the desired property modifications. Appearance formatting can be introduced in the HTMLCellFormatting event handler. Finally, run the exporter. [VB.NET] Export to PDF Private Sub btnExportPDF_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExportPDF.Click Dim sfd As New SaveFileDialog() sfd.Filter = [String].Format("{0} (*{1})|*{1}", "PDF Files", ".pdf") If sfd.ShowDialog() = DialogResult.OK Then Dim exporter As New ExportToPDF(Me.RadGridView1) exporter.FileExtension = "pdf" exporter.HiddenColumnOption = Telerik.WinControls.UI.Export.HiddenOption.DoNotExport exporter.ExportVisualSettings = True exporter.PageTitle = "My Page Title" exporter.SummariesExportOption = SummariesOption.DoNotExport exporter.FitToPageWidth = True exporter.Scale = 1.2F exporter.TableBorderThickness = 1 exporter.PdfExportSettings.PageHeight = 210 exporter.PdfExportSettings.PageWidth = 297 exporter.PdfExportSettings.Author = "Telerik" AddHandler exporter.HTMLCellFormatting, AddressOf exporter_HTMLCellFormatting exporter.RunExport(sfd.FileName) MessageBox.Show("Export completed") End If End Sub Sub exporter_HTMLCellFormatting(ByVal sender As System.Object, ByVal e As HTMLCellFormattingEventArgs) If e.GridRowIndex > -1 AndAlso e.GridColumnIndex = RadGridView1.Columns ("SalesLastYear").Index Then Dim value As Integer = Convert.ToInt32(RadGridView1.Rows(e.GridRowIndex).Cells (e.GridColumnIndex).Value) If value > 1500000 Then 'cells with value over 1500000 will be yellow e.HTMLCellElement.Styles.Add("background-color", ColorTranslator.ToHtml(Color.Yellow)) End If
647
648
Exporting to HTML
This method offers excellent export performance and creates an html formatted file, which can be opened in a browser or MS Word.
FileExtension - defines the file extension for the exported file HiddenColumnOption and HiddenRowOption properties to determine how hidden rows and columns should behandled by theexporter. ExportVisualSettings property defines wether to export the visualsettings (themes) too. TableCaption-specifies the table caption SummariesExportOption - defines how summary rows should be handled HTMLCellFormatting event -gives access to a single cells html element that allows you to make additional formatting for every html cell related to the exported RadGridView HTMLTableCaptionFormatting - can be used to make an additional formatting on the html caption table elemen
The following code creates a sample html exporter in the btnExportHTML_Click event handler:
649
650
Exporting to CSV
This method offers excellent export performance. It creates a csv file and supports formatting events to allow customizing exported data. The most interesting properties are:.
FileExtension - defines the file extension for the exported file HiddenColumnOption and HiddenRowOption properties to determine how hidden rows and columns should behandled by theexporter. SummariesExportOption - defines how to handle the summary rows CSVCellFormatting event -gives access to a single cells element that allows you to replace the actual value for every cell related to the exported RadGridView CSVTableCaptionFormatting -can be used together with the public method AddCustomCSVRow. It allows for adding and formatting new custom rows on the top of the csv file
Here is a sample code that creates export to CSV functionality in the btnExportCSV event handler [VB.NET] Export to CSV Private Sub btnExportCSV_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExportCSV.Click Dim sfd As New SaveFileDialog() sfd.Filter = [String].Format("{0} (*{1})|*{1}", "CSV Files", ".csv") If sfd.ShowDialog() = DialogResult.OK Then
651
652
21.15Summary
In this chapter you became familiar with the RadGridView control, using the Smart Tag, Property Builder and Properties window to configure the grid and to bind the grid to data. You learned how to add special purpose column types at design-time and in code, how to group/filter/sort data based on user input at runtime, by hand at design-time and programmatically in code. You displayed hierarchical data from multiple related tables in the grid. You used the RadGridView Virtual Mode feature to take low-level control over the grid's refresh
653
654
22.1 Objectives
Learn how to access the underlying combo and grid in the RadMultiColumnComboBox. Learn how to bind data to the control. Filter the list based on user entry. React to user selections in the list.
22.2 Introduction
The RadMultiColumnComboBox is a special case of combobox control with a RadGridView integrated in its dropdown. The drop down display has the rich capabilities of the grid view, but you can stilluse the control in a limited amount of space. Theimage below shows the structure of the control:
1. The drop-down element is represented by the MultiColumnComboBoxElement property. Use this element to set the drop-down style, animation and sizing as you would do for the regular combobox. The control can alsoautomatically filterentries in the gridas characters are typed in.
2. The EditorControl property of the MultiColumnComboBoxElement gives you a reference to the RadGridView control. From there you can access grid properties, i.e. MasterGridViewTemplate, columns, cells, etc.
655
RadMultiColumnComboBox Setup
1. Add a RadMultiColumnComboBox control to the form. 2. In the "Choose DataSource" drop down choose "Add Project Data Source...". This step will display the Data Source Configuration Wizard dialog. 3. In the "Choose a Data Source Type" page of the wizard, select "Database" and click the Next button. 4. In the "Choose Your Data Connection" page of the wizard, click "New Connection...". This will display the Add Connection dialog. 5. In the Add Connection dialog, set the Data Source to "Microsoft Access Database File (OLE DB)", and the Database File Name to "Furniture.mdb". Click OK to close the dialog. Furniture.mdb can be found in the RadControls for Winforms installation directory in the \Examples\QuickStart\Datasources directory.
656
So far the drop down list is a little narrow and the drop down can't be resized. Except for the Photo column, the columns are a little narrow, and we don't really need to see the "ID" column. Let's fix these issues: 10. Set the RadMultiColumnComboBox DropDownSizingMode to UpDownAndRightBottom and the Text property to "".
657
658
659
[VB] Using the RadMultiColumnComboBoxElement Reference Private Sub RadForm1_Load(sender As Object, e As EventArgs) Dim contacts As New List(Of Contact)() contacts.Add(New Contact("Akina", "Yamada", "[email protected]")) contacts.Add(New Contact("Bob", "Coffee", "[email protected]")) contacts.Add(New Contact("Ajit", "Singh", "[email protected]")) contacts.Add(New Contact("Chavdar", "Ivanov", "[email protected]")) radMultiColumnComboBox1.DataSource = contacts radMultiColumnComboBox1.DisplayMember = "First" radMultiColumnComboBox1.ValueMember = "Email" Dim combo As RadMultiColumnComboBoxElement = radMultiColumnComboBox1.MultiColumnComboBoxElement combo.DropDownWidth = radMultiColumnComboBox1.Width combo.ArrowButtonMinWidth = 100 End Sub [C#] Using the RadMultiColumnComboBoxElement Reference private void RadForm1_Load(object sender, EventArgs e) { List<Contact> contacts = new List<Contact>(); contacts.Add(new Contact("Akina", "Yamada", "[email protected]")); contacts.Add(new Contact("Bob", "Coffee", "[email protected]")); contacts.Add(new Contact("Ajit", "Singh", "[email protected]")); contacts.Add(new Contact("Chavdar", "Ivanov", "[email protected]")); radMultiColumnComboBox1.DataSource = contacts; radMultiColumnComboBox1.DisplayMember = "First"; radMultiColumnComboBox1.ValueMember = "Email"; RadMultiColumnComboBoxElement combo = radMultiColumnComboBox1.MultiColumnComboBoxElement; combo.DropDownWidth = radMultiColumnComboBox1.Width; combo.ArrowButtonMinWidth = 100; } Gotcha! When binding to a list of custom objects, be sure to scope the properties of your object "public". Leaving them at their "private" defaults will not generate errors, but you still won't see data. You can programmatically drop down the list using the MultiColumnComboBoxElement ShowPopup() method. [VB] The ShowPopup Method Private Sub btnShowPopup_Click(sender As Object, e As EventArgs) Dim combo As RadMultiColumnComboBoxElement = radMultiColumnComboBox1.MultiColumnComboBoxElement combo.ShowPopup()
660
Filtering
To filter the grid as the user types in the edit box of the combo:
Set the AutoFilter property to true. Set the PropertyName to the column that you want to filter against (usually DisplayMember). Set the desired Operator to one of the FilterOperator enumerated values. Build a FilterDescriptor that describes the rules used to filter the data and add the expression to the grid's MasterTemplate FilterDescriptor collection.
[VB] Filtering the List radMultiColumnComboBox1.AutoFilter = true; FilterDescriptor filter = new FilterDescriptor(); filter.PropertyName = radMultiColumnComboBox1.DisplayMember; filter.Operator = FilterOperator.StartsWith; combo.EditorControl.MasterTemplate.FilterDescriptors.Add(filter); [C#] Filtering the List radMultiColumnComboBox1.AutoFilter = True Dim filter As FilterDescriptor = New FilterDescriptor() filter.PropertyName = radMultiColumnComboBox1.DisplayMember filter.Operator = FilterOperator.StartsWith combo.EditorControl.MasterTemplate.FilterDescriptors.Add(filter) This example used a generic list of Contact objects with fields "First", "Last" and "Email". DisplayMember in this case was "First".
661
"Sender" in this event handler is the RadMultiColumnComboBox itself. Retrieve the SelectedItem and cast it to a GridViewDataRowInfo. GridViewDataRowInfo has a DataBoundItem propertythat is the actual object that is being bound to a given row. [VB] Handling the SelectedIndexChanged Event Private Sub radMultiColumnComboBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Dim rowInfo As GridViewDataRowInfo = TryCast((TryCast(sender, RadMultiColumnComboBox)).SelectedItem, GridViewDataRowInfo) Dim contact As Contact = TryCast(rowInfo.DataBoundItem, Contact) If contact <> Nothing Then lblSelected.Text = contact.First + " " + contact.Last + " " + contact.Email End If End Sub [C#] Handling the SelectedIndexChanged Event private void radMultiColumnComboBox1_SelectedIndexChanged(object sender, EventArgs e) { GridViewDataRowInfo rowInfo = (sender as RadMultiColumnComboBox).SelectedItem as GridViewDataRowInfo; Contact contact = rowInfo.DataBoundItem as Contact; if (contact != null) { lblSelected.Text = contact.First + " " + contact.Last + " " + contact.Email; } }
22.5 Summary
In this chapter you learned how to access the RadMultiColumnComboBox underlying combo and grid controls. You learned how to bind data to the control, how to filter the data in the drop down based on user entry and how to react to user selections by handling the SelectedIndexChanged event.
662
23.1 Objectives
Display, navigate and manage hierarchical data using the RadTreeView control. Learn to add, move, remove, iterate and locate nodes programmatically. Learn how to edit nodes. Use the RadBreadCrumb control to help the user keep track of their location in deeply nested hierarchical structures. Implementdrag-and-drop within the treeview, between treeviews and to other controls. Use context menus. Learn about RadTreeView specific databinding issues including binding to self referencing data, binding to related data, writing to and from XML and load-on-demand.
23.2 Introduction
RadTreeView is the supercharged tree view component for Windows Forms that displays, manages, and navigates hierarchical data structures. The product offers advanced features like drag-and-drop, load-ondemand, filtering, context menus and data binding. Here are just a few features: RadTreeView supports drag and drop within the same tree and between RadTreeView controls. The position indication cursor provides feedback to the user so that nodes can be dropped above, below or as a child of a given node. When dragging to a hidden or collapsed node the control will scroll up/down and automatically open the collapsed node. Drag and drop behavior is customizable at the treeview and node levels, allowing you to restrict interactions between source and target nodes.
RadTreeView binds to hierarchical data for most popular databases, custom business objects and XML. RadTreeView binds to any object that supports IList, IListSource or IBindingList. RadTreeView can also load and save XML directly to file
663
Expand RadTreeView functionality by adding context menus either for the entire treeview or to each node. You have the capability to attach a different context menu to each tree node. Each context menu can be individually styled.
You can mix check boxes and radio buttons to form "option trees".Both can be
664
665
Right click the RadTreeView and select Open Property Builder from the context menu. You will see a set of buttons on the left side of the RadTreeView Property Builder and a preview of the treeview below the buttons. Click the far left button (a green "Plus" button that adds nodes) three times to add three root level nodes. Click the first node and enter "Email Contacts" in the Text entry. In the Advanced tab set its Name property to the same value. Click the second node and enter "Lists" in the Text entry. In the Advanced tab set its Name property to the same value. Click the third node and enter "Reports" in the Text entry. In the Advanced tab set its Name property to the same value. Click OK to close the Property Builder.
666
667
5. Add code to the form load event handler. The code here will add new nodes to the existing root nodes. Also notice that the "Reports" nodes ContextMenu properties are assigned the RadContextMenu DropDown property. [VB] Handling the Load Event Handler Private Sub RadForm1_Load(sender As Object, e As EventArgs) ThemeResolutionService.ApplicationThemeName = "Office2007Silver" Dim node As RadTreeNode = radTreeView1.Nodes("Email Contacts").Nodes.Add("Bob Tony") node.Selected = True radTreeView1.Nodes("Email Contacts").Nodes.Add("Sue Winchell") radTreeView1.Nodes("Email Contacts").Nodes.Add("Lui Sang") radTreeView1.Nodes("Lists").Nodes.Add("Priorities") radTreeView1.Nodes("Lists").Nodes.Add("Opportunities") radTreeView1.Nodes("Lists").Nodes.Add("Issues") node = radTreeView1.Nodes("Reports").Nodes.Add("June Sales") node.ContextMenu = radContextMenu1 node = radTreeView1.Nodes("Reports").Nodes.Add("July Sales") node.ContextMenu = radContextMenu1 node = radTreeView1.Nodes("Reports").Nodes.Add("First Quarter Summary") node.ContextMenu = radContextMenu1 node = radTreeView1.Nodes("Reports").Nodes.Add("Second Quarter Summary") node.ContextMenu = radContextMenu1 End Sub [C#] Handling the Load Event Handler private void RadForm1_Load(object sender, EventArgs e) { ThemeResolutionService.ApplicationThemeName = "Office2007Silver";
668
669
Below thestrip buttons pane is a representation of the nodes as they will appear on the form. Click individual nodes to set node-level properties or use button to delete or move them.
670
Above the strip of buttons you'll see the "RadTreeView properties" tab. Select thistab to view tree view level properties in the right hand pane of the dialog.
Use the button found on the far right side of the dialog to toggle between "Settings" and "Advanced". Use Advanced to get a full list of properties for the RadTreeView or selected RadTreeNode.
671
672
Here's a slightly more complicated example with three levels of nodes. Notice that the Nodes.Add() method returns the RadTreeNode that was added to the collection. [VB] Adding Multiple Levels of Nodes Dim rootNode As New RadTreeNode("Root") radTreeView1.Nodes.Add(rootNode) rootNode.Nodes.Add("Child Node 1") rootNode.Nodes.Add("Child Node 2") rootNode.Nodes.Add("Child Node 3") Dim childNode4 As RadTreeNode = rootNode.Nodes.Add("Child Node 4") rootNode.Nodes.Add("Child Node 5") childNode4.Nodes.Add("Child Node 4 A") childNode4.Nodes.Add("Child Node 4 B") childNode4.Nodes.Add("Child Node 4 C") radTreeView1.ExpandAll() [C#] Adding Multiple Levels of Nodes RadTreeNode rootNode = new RadTreeNode("Root"); radTreeView1.Nodes.Add(rootNode); rootNode.Nodes.Add("Child Node 1"); rootNode.Nodes.Add("Child Node 2"); rootNode.Nodes.Add("Child Node 3"); RadTreeNode childNode4 = rootNode.Nodes.Add("Child Node 4"); rootNode.Nodes.Add("Child Node 5"); childNode4.Nodes.Add("Child Node 4 A"); childNode4.Nodes.Add("Child Node 4 B"); childNode4.Nodes.Add("Child Node 4 C"); radTreeView1.ExpandAll();
If you have a string that describes a hierarchy (a file path, or an organization chart for example)and is delimited with a specific character, the RadTreeView AddNodeByPath() method will automatically place nodes to the correct level of the hierarchy. Before calling the method, set the PathSeparator property to the
673
Selecting Nodes By default the Multiselect property is False and you can use the SelectedNode property to retrieve the single node. If you set Multiselect to True, use the SelectedNodes collection. This example iterates the selected nodes and changes the background colors for each node. [VB] Iterating Selected Nodes Private Sub btnSelectedNodes_Click(sender As Object, e As EventArgs) For Each node As RadTreeNode In radTreeView1.SelectedNodes node.BackColor = Color.AliceBlue node.BackColor2 = Color.LightBlue Next End Sub [C#] Iterating Selected nodes private void btnSelectedNodes_Click(object sender, EventArgs e) { foreach (RadTreeNode node in radTreeView1.SelectedNodes) { node.BackColor = Color.AliceBlue; node.BackColor2 = Color.LightBlue; } }
674
Move Nodes Someoperations require nodes to be reordered within the collection using the Nodes collection Move() method. The method takes the index of the node to be moved and the index of its new location.Here's an example that moves the selected node to last place among its siblings. [VB] Relocating Nodes Private Sub btnReorder_Click(sender As Object, e As EventArgs) ' move selected node to the end of the list ' Note: Parent and Index properties are deprecated only for "getters" If (radTreeView1.SelectedNode <> Nothing) AndAlso (radTreeView1.SelectedNode.Parent <> Nothing) Then Dim nodes As RadTreeNodeCollection = radTreeView1.SelectedNode.Parent.Nodes nodes.Move(radTreeView1.SelectedNode.Index, nodes.Count - 1) End If End Sub [C#] Relocating Nodes private void btnReorder_Click(object sender, EventArgs e) { // move selected node to the end of the list // Note: Parent and Index properties are deprecated only for "getters" if ((radTreeView1.SelectedNode != null) && (radTreeView1.SelectedNode.Parent != null)) { RadTreeNodeCollection nodes = radTreeView1.SelectedNode.Parent.Nodes; nodes.Move(radTreeView1.SelectedNode.Index, nodes.Count - 1); } }
675
You can find the complete source for this project at: \Treeview\<VB|CS>\WorkingWithNodes Locating Nodes RadTreeView hasa filtering functionality, which will return all nodes that contain the specified text and all the parent nodes results. Example Title Private Sub CommandBarButton1_Click(sender As System.Object, e As System.EventArgs) Handles CommandBarButton1.Click radTreeView1.Filter = commandBarTextBox1.Text Dim filteredResults As RadTreeNode() = radTreeView1.Nodes.ToArray() End Sub The filteredResults array contains one node ("Telerik corp") which has one node in its node collection ("Company Directors") which has the searched node in its nodes collection ("Bil").
676
Node Images
RadTreeView can react visually as nodes are selected, opened and closed using image properties. Each node has image properties with three ways to access:
Image: An Image class that can be assigned directly without using an ImageList. ImageIndex: The position of an image within an ImageList. ImageKey: The identifier for an image within an ImageList.
[VB] Setting Image and "Far" Image Index Dim rootNode As New RadTreeNode("Telerik corp") rootNode.Image = Image.FromFile("C:\image.png") rootNode.ImageKey = "imageName.png" rootNode.ImageIndex = 0 radTreeView1.Nodes.Add(rootNode) [C#] Setting Image and "Far" Image Index RadTreeNode rootNode = new RadTreeNode("Telerik corp); rootNode.Image = Image.FromFile(@"C:\image.png"); rootNode.ImageKey = "imageName.png"; rootNode.ImageIndex = 0; radTreeView1.Nodes.Add(rootNode);
677
Node Formatting
Similar to RadGridView, RadTreeView is virtualized. Its visual nodes (TreeNodeElement) are reused by the data nodes (RadTreeNode) which bring increased performance and optimized memory footprint. You can easily format node element by handling the NodeFormatting event. The arguments of this event return the visual Node (and the data Node that is currently assigned to it) that is currently formatted and which you can additionally style.
The purpose of the example that follows is to demonstrate how you can show different images for the RadTreeView nodes depending on their logical state. We are going to simulate a tree of files and folders displaying an image of a closed folder when a node that contains other nodes is collapsed and displaying an image of an opended folder when a node that contains other nodes is expanded. 1. Let's fill RadTreeView with some sample nodes which represent files and folders:
678
2. Then, add three images as project resources. These images will indicate if a node is a file, an opened folder or a closed folder 3. Handle the NodeFormatting event implementing, setting the image to the Image property of the ImageElement. This element is responsible for containing the image of the visual NodeElement: [VB.NET] Formatting nodes Private folderOpen As Bitmap = My.Resources.folder_open Private folderClose As Bitmap = My.Resources.folder_close Private file As Bitmap = My.Resources.file Private Sub radTreeView1_NodeFormatting(ByVal sender As Object, ByVal e As TreeNodeFormattingEventArgs) If e.Node.Nodes.Count > 0 Then If e.Node.Expanded Then e.NodeElement.ImageElement.Image = folderOpen Else e.NodeElement.ImageElement.Image = folderClose End If Else e.NodeElement.ImageElement.Image = file End If End Sub [C#] Formatting nodes Bitmap folderOpen = SamplesCS.Properties.Resources.folder_open; Bitmap folderClose = SamplesCS.Properties.Resources.folder_close; Bitmap file = SamplesCS.Properties.Resources.file; void radTreeView1_NodeFormatting(object sender, TreeNodeFormattingEventArgs e) { if (e.Node.Nodes.Count > 0) {
679
680
You can find the complete source for this project at: \Treeview\<VB|CS>\WorkingWithNodesWalkThrough Preparing the Project 1. Create a new Windows Forms application. 2. In the Solution Explorer, delete the default form. 3. Also in the Solution Explorer, right-click the project and select Add | New Item... from the context menu. 4. Select the "Telerik RadForm" template and click the Add button to close the dialog. 5. Add a standard ImageList component to the form and name it "ilIcons". Use the ImageList Smart Tag to set the Image Bit Depth to "Depth32Bit". In the Properties window, set the ImageList TransparentColor to "Fuchsia". Click the ImageList Smart Tag "Choose Images" option and add images to represent the ideas below.
681
Library Class Property Method You can typically find images in the Visual Studio Common7\VS2008ImageLibrary\1033 directory in "VS2008ImageLibrary.zip". There are copies of the images used in this project at \Treeview\<VB|CS>\WorkingWithNodesWalkThrough\Images. You can add these to the ImageList and rename them to "library", "class", "property" and "method" for easier referencing in code.
6. Change the new RadForm1 to be the startup form. Form Setup 1. From the Toolbox, add a RadMenu to the form. In the designer, enter "File" to the "Type here" space on the menu. From the Smart tag click the"Add new" link of the "File" item, add three more menu Items and set properties:
Name = "miOpen", Text = "Open" Name = "miClose", Text = "Close" Name = "miExit", Text = "Exit"
682
2. Add a RadStatusStrip to the form. Add a RadLabelElement to the status strip, Name it "lblStatus" and set the Text = "". 3. Add two RadPanels, Dock the first one to "Top" and the second one to "Bottom". Change the top panel size to take approximately three quaters of the available space and the bottom panel sizeto take the rest of the space. Set both panels Text = "" and set the second panel BackColor to "Info". The form should look like the screenshot:
683
[C#] Adding References System; System.IO; System.Reflection; System.Text; System.Windows.Forms; Telerik.WinControls; Telerik.WinControls.UI;
2. Add a private helper method to return a comma-delimited list of parameter types, e.g. "(String, int, int, object)". It takes an array ofParameterInfo from the System.Reflection namespace. We will use this later to get information about constructors and methods. [VB] Getting a Formatted List of Parameters ' return a string surrounded with parenthesis and containing ' a comma-delimited list of parameter types, e.g. ' "(String, String, Int32)" Private Function GetParameterList(parameters As ParameterInfo()) As String Dim builder As New StringBuilder("(") Dim i As Integer = 0 For Each parameter As ParameterInfo In parameters builder.Append(parameter.ParameterType.Name) If System.Threading.Interlocked.Increment(i) < parameters.Length Then builder.Append(", ") End If Next builder.Append(")") Return builder.ToString() End Function [C#] Getting a Formatted List of Parameters // return a string surrounded with parenthesis and containing // a comma-delimited list of parameter types, e.g. // "(String, String, Int32)" private string GetParameterList(ParameterInfo[] parameters) { StringBuilder builder = new StringBuilder("("); int i = 0; foreach (ParameterInfo parameter in parameters)
684
685
686
687
688
689
Responding to Events Lets improve the example by showing detail in the lower panel for selected nodes. We will be responding to the treeview SelectedNodeChanged event and retrieving the Tag value if there is one. The Tag may hold an Assembly, ConstructorInfo, MethodInfo, PropertyInfo or TypeInfo object.The information in these classes will
690
691
692
693
694
Data Binding
Simple Data Binding Before we bind to hierarchical data, lets use the treeview as a simple list to see the most minimal databinding possible. You can find the complete source for this project at: \Treeview\<VB|CS>\DatabindingTreeView Set Program.cs to start with the form SimpleData. Start with a RadTreeView on a form or RadForm. Using the RadTreeView DataSource property, add a project data source that points at the NWind.mdb file found in the RadControls for Winforms installation directory under \Examples\QuickStart\DataSources (see the Data Binding chapter for more information on how to do this). We only need three lines of code and the first line is generated automatically when you configure the DataSource.
695
Binding Hierarchical Data Overview To get best use of the treeview, databinding has to take data hierarchy into account. There are a couple of ways to approach this:
Bind a single table that references to itself. For example the data might include an "ID" and a "ParentID" column. Or as in the case of the NWind.mdb Employees table there is a "EmployeeID" that uniquely identifies each record and a "ReportsTo" column that points to a parent record's EmployeeID. Theroot level node will have no parent record as is the case for the "Vice President, Sales" that has a null "ReportsTo" value.
696
Bind the treeview to multiple tables and add RelationBindings that describe how one table relates to another. For example, use the MusicCollection.mdb database that has three tables Artists, Albums forthe artists and Songs that belong to the Albums.
Binding Self Referencing Data You can find the complete source for this project at: \Treeview\<VB|CS>\Databinding Set Program.cs to start with the form "SelfReferencing". Using the previous simple binding example we only need to specify a couple of properties to implement self referencing that will produce a true hierarchy display of the data. You can see in the code below that we only need to define:
DisplayMember - the name of the field that populates the Text property of each child node. ChildMember - the name of the child data filend which takes part in the relation. ParentMember - the name of the parent data field which takes part in the relation.
[VB] Binding Self Referencing Data Private Sub RadForm1_Load(sender As Object, e As EventArgs) Me.employeesTableAdapter.Fill(Me.nwindDataSet.Employees) radTreeView1.DataSource = Me.nwindDataSet.Employees radTreeView1.DisplayMember = "Title" radTreeView1.ChildMember = "EmployeeID" radTreeView1.ParentMember = "ReportsTo" End Sub [C#] Binding Self Referencing Data private void RadForm1_Load(object sender, EventArgs e) { this.employeesTableAdapter.Fill(this.nwindDataSet.Employees); radTreeView1.DataSource = this.nwindDataSet.Employees; radTreeView1.DisplayMember = "Title"; radTreeView1.ChildMember = "EmployeeID"; radTreeView1.ParentMember = "ReportsTo"; }
697
Binding Related Data You can find the complete source for this project at: \Treeview\<VB|CS>\Databinding Set Program.cs to start with the form "RelatedData". Related data can take the form of:
DataTables in a DataSet participating in relations represented by a DataRelation. Business Objects that have nested collections. In this case items in nested collections are considered to be child records of the business object that contains the collections.
The configuration of relational data is described by adding to the RelationBindings collection of RadTreeView. Minimally you need to set the data source and thedisplay member for the control and datasource,display member,parent member and child member (or the parentChildMember when their value isequal)for the relation. For example: [VB] Adding a RelationBinding Me.radTreeView1.DataSource = this.artistsBindingSource Me.radTreeView1.DisplayMember = "ArtistName" radTreeView1.RelationBindings.Add(albumsBindingSource, "AlbumName", "ArtistID"); [C#] Adding a RelationBinding this.radTreeView1.DataSource = this.artistsBindingSource; this.radTreeView1.DisplayMember = "ArtistName"; radTreeView1.RelationBindings.Add(albumsBindingSource, "AlbumName", "ArtistID"); Lets walk through binding the treeview to the Artists/Albums/Songs trilogy of tables. 1. Start with a RadTreeView on a Form or RadForm. 2. Find the treeview DataSource property in the Properties Window, drop down the list and select Add Project Data Source. This will display the Data Source Configuration Wizard. 3. In the "Choose a Data Source Type" page of the wizard select the Database icon, then click the Next
698
Click the New Connection button. In the "Add Connection" dialog click the Change button, select "Microsoft Access Database File" and click the OK button. Next to the Database file name entry, click the Browse button and locate the MusicCollection.mdb file in the installation directory under \Examples\QuickStart\DataSources. Click the OK button to close the "Add Connection" dialog.
5. When prompted if you would like to copy the local data file to your project click the No button. 6. In the "Save the Connection String to the Application Configuration File" page of the wizard click the Next button. 7. In the "Choose Your Database Objects" page of the wizard click the Tables checkbox (this will automatically check the Albums, Artists and Songs tables). 8. Click the Finish button to complete and close the wizard dialog. 9. Select each table to create components
Back in the treeview DataSource property, drop down the list and locate the "Albums" table from under the "MusicCollectionDataSet" dataset.
Select the "Artists" table. Select the "Songs" table. You should now have the DataSet for the music collection and pairs of BindingSource and TableAdapter components for each table in the component tray.
10. Add the following statements to the form Load event handler
Add a "Imports" (VB) or "uses" (C#) statement referencing Telerik.WinControls.UI to support the RelationBinding object.
699
Include RelationBinding.Add() methods for both "ArtistsAlbums" and "AlbumSongs". Define the RadTreeView RootRelationDisplayname property. Set the DataSource to use the "artistsBindingSource" component. [VB] Loading Data and Defining Relation Bindings Private Sub RelatedData_Load(sender As Object, e As EventArgs) ' generated automatically by configuration Me.songsTableAdapter.Fill(Me.musicCollectionDataSet.Songs) Me.artistsTableAdapter.Fill(Me.musicCollectionDataSet.Artists) Me.albumsTableAdapter.Fill(Me.musicCollectionDataSet.Albums) ' added by hand to define the relation bindings Me.radTreeView1.DataSource = this.artistsBindingSource Me.radTreeView1.DisplayMember = "ArtistName" radTreeView1.RelationBindings.Add(albumsBindingSource, "AlbumName", "ArtistID") radTreeView1.RelationBindings.Add(songsBindingSource, "SongName", "AlbumID") End Sub [C#] Loading Data and Defining Relation Bindings private void RelatedData_Load(object sender, EventArgs e) { // generated automatically by configuration this.songsTableAdapter.Fill(this.musicCollectionDataSet.Songs); this.artistsTableAdapter.Fill(this.musicCollectionDataSet.Artists); this.albumsTableAdapter.Fill(this.musicCollectionDataSet.Albums); // added by hand to define the relation bindings this.radTreeView1.DataSource = this.artistsBindingSource; this.radTreeView1.DisplayMember = "ArtistName"; radTreeView1.RelationBindings.Add(albumsBindingSource, "AlbumName", "ArtistID"); radTreeView1.RelationBindings.Add(songsBindingSource, "SongName", "AlbumID"); }
700
Using XML Data There are two approaches to consuming XML data:
Bind to a DataSet and reading the XML into the DataSet. Use special methods of RadTreeView to save and load the XML directly, i.e.serialize/deserialize the XML.
Binding to XML Data You can find the complete source for this project at: \Treeview\<VB|CS>\Databinding Set Program.cs to start with the form "XMLBinding".
701
702
Saving and Loading XML You can find the complete source for this project at: \Treeview\<VB|CS>\Databinding Set Program.cs to start with the form "XMLSerialize". The contents of a RadTreeView can be serialized as XML directly to a file. In the sample project, nodes can be added to create an arbitrary tree. The Save button calls the RadTreeView SaveXML() method. SaveXML() takes either a file path to save your XML directly to disk or a stream that you could use to save the XML in a database.
The saved XML looks something like the example below. Notice that it even retains the current node selection.
703
The code to perform the save is using OpenSaveDialog and OpenLoadDialog, but is otherwise a one-liner. [VB] Load and Save TreeView Structure as XML Private Sub btnSave_Click(sender As Object, e As EventArgs) Dim dialog As New SaveFileDialog() dialog.Filter = "XML Files|*.xml" If dialog.ShowDialog() = DialogResult.OK Then radTreeView1.SaveXML(dialog.FileName) End If End Sub Private Sub btnLoad_Click(sender As Object, e As EventArgs) Dim dialog As New OpenFileDialog() dialog.Filter = "XML Files|*.xml" If dialog.ShowDialog() = DialogResult.OK Then radTreeView1.LoadXML(dialog.FileName) End If End Sub [C#] Load and Save TreeView Structure as XML private void btnSave_Click(object sender, EventArgs e) { SaveFileDialog dialog = new SaveFileDialog(); dialog.Filter = "XML Files|*.xml"; if (dialog.ShowDialog() == DialogResult.OK) { radTreeView1.SaveXML(dialog.FileName); } } private void btnLoad_Click(object sender, EventArgs e) { OpenFileDialog dialog = new OpenFileDialog(); dialog.Filter = "XML Files|*.xml"; if (dialog.ShowDialog() == DialogResult.OK) { radTreeView1.LoadXML(dialog.FileName); } } Saving to a stream requires a stream descendant instance such as MemoryStream. From there you can use the array of bytes from GetBuffer() and send the bytes to a database or other persistence medium. [VB] Using SaveXML() with a Stream Dim stream As New MemoryStream() radTreeView1.SaveXML(stream) RadMessageBox.Show(stream.GetBuffer().Length.ToString()) [C#] Using SaveXML() with a Stream
704
"Load-on-demand" where large or potentially unknown amountsof data are loaded only when needed. Surround batch changes to the tree with BeginUpdate() and EndUpdate()calls to avoid constant repainting.
The Load On Demand feature helps reduce performance and memory costs incurred when all nodes are loaded at one time. To benefit from this feature, you just need to handle the NodesNeeded event. This event is fired when you try to expand a node. The event arguments of this event return contain the Parent node that you are trying to expand and the Nodes collection that you should fill with subnodes. The code snippet below demonstrates how you can handle the NodesNeeded event and load 500 nodes to any expanded node: [VB] Load on Demand Private Sub radTreeView1_NodesNeeded(ByVal sender As Object, ByVal e As Telerik.WinControls.UI.NodesNeededEventArgs) Handles radTreeView1.NodesNeeded ' measure how long this takes Dim stopwatch As New Stopwatch() stopwatch.Start() Dim count As Integer = 0 ' get the data for all child nodes Dim weatherStations As String() = My.Resources.WeatherStations.Split(New String() {Constants.vbCrLf}, StringSplitOptions.RemoveEmptyEntries) For Each station As String In weatherStations e.Nodes.Add(New RadTreeNode(station)) count += 1 Next ' show performance results stopwatch.[Stop]() Dim ts As TimeSpan = stopwatch.Elapsed lblStatus.Text = [String].Format("{0:00}:{1:00}:{2:00}.{3:00} loading {4} nodes", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds / 10, count) Me.radTreeView1.EndUpdate() End Sub [C#] Load on Demand void radTreeView1_NodesNeeded(object sender, NodesNeededEventArgs e) { // measure how long this takes Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); int count = 0; // get the data for all child nodes string[] weatherStations = Properties.Resources.WeatherStations.Split( new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); foreach (string station in weatherStations) { e.Nodes.Add(new RadTreeNode(station)); count++; } // show performance results stopwatch.Stop(); TimeSpan ts = stopwatch.Elapsed;
705
We are only loading children to the root level nodes and no further. We're using a System.Diagnostics StopWatch component to measure the amount of time it takes to build the tree.
[VB] Load On Demand Private Sub radTreeView1_NodeExpandedChanged(sender As Object, e As Telerik.WinControls.UI.RadTreeViewEventArgs) ' measure how long this takes Dim stopwatch As New Stopwatch() stopwatch.Start() Dim count As Integer = 0 ' the node is expanded, hasn't been loaded yet, and only load the first level If e.Node.Expanded AndAlso Not e.Node.LoadedOnDemand AndAlso e.Node.Level = 0 Then ' don't repaint till we're done ' get the data for all child nodes Dim weatherStations As String() = Properties.Resources.WeatherStations.Split(New String() {vbCr & vbLf}, StringSplitOptions.RemoveEmptyEntries) For Each station As String In weatherStations e.Node.Nodes.Add(station) System.Math.Max(System.Threading.Interlocked.Increment(count),count - 1) Next ' flag the node as having been loaded e.Node.LoadedOnDemand = True End If End If ' show performance results stopwatch.[Stop]() Dim ts As TimeSpan = stopwatch.Elapsed lblStatus.Text = [String].Format("{0:00}:{1:00}:{2:00}.{3:00} loading {4} nodes", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds / 10, count) End Sub [C#] Load On Demand private void radTreeView1_NodeExpandedChanged(object sender, Telerik.WinControls.UI.RadTreeViewEventArgs e) { // measure how long this takes Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); int count = 0; // the node is expanded, hasn't been loaded yet, and only load the first level if (e.Node.Expanded && !e.Node.LoadedOnDemand && e.Node.Level == 0)
706
RadTreeView has the ability to bind to related data of custom objects which have member collections of related objects (ORM generated classes for example). Consider the following class diagram:
707
There are three classes named Customer, Order and Order_Detail. The data relations in the case of custom objects are represented by properties which provide references to collections of related objects. In this case the Customer class has a property named Orders which is a collection of Order objects. This is the first relation. The second relation is the Order_Details property in the Order class, it offers a reference to a collection of Order_Details. Once you have such class composition, it is trivial for RadTreeView to represent it visually in your application. The two steps that must be done are these: 1. Set the DataSource of RadTreeView to a collection of your root objects (a collection of Customer object in this case): [VB] Set RadTreeView data source Dim customers As IEnumerable(Of Customer) = context.GetTable(Of Customer)().ToList() Me.RadTreeView1.DataSource = customers [C#] Set RadTreeView data source IEnumerable<Customer> customers = context.GetTable<Customer>().ToList(); this.radTreeView1.DataSource = customers; 2. Set DisplayMember corresponding to the DisplayMembers of the different types of objects and set the ChildMember corresponding to the names of the properties that represent the collections of subobjects. [VB.NET] Set he Display and Child members
708
Binding RadTreeView to self referencing data differs form binding to related data in that RadTreeView is bound to a single list instead of multiple related lists. In order to set the parent-child relation between the records of the data source, we should set the ParentMember and ChildMember properties to the respective fields this data source. If the parent ID for a record does not have a respective value in the child ID field of the records, then that record is considered to have no parents. The following example demonstrates how to bind RadTreeView to a self referencing DataTable. [VB.NET] Bind RadTreeView to self referencing data Public Sub New() InitializeComponent() Me.RadTreeView1.DisplayMember = "name" Me.RadTreeView1.ValueMember = "id" Me.RadTreeView1.ParentMember = "pid" Me.RadTreeView1.DataSource = Me.GetSampleData() Me.RadTreeView1.DataMember = "Nodes" End Sub Private Function GetSampleData() As DataTable Dim dt As New DataTable() Dim dc As New DataColumn() dc.ColumnName = "id"
709
710
711
Editing Nodes
By default RadTreeView does not allow node editing. If the AllowEditing property is set to true, the user may select a node and either press F2 to initiate editing or simply double click the node. By default a text editor is invoked and allows the editing of the node label. When the edit process ends the entered value is assigned to the node Text property. If the user cancels editing by pressing Escape the value is not persisted. To edit progrmatically, call BeginEdit() to initiate editing the selected node and EndEdit() to conclude editing. EndEdit() takes a single "cancelEdit" parameter; when cancelEdit is true, changes are abandoned. You can find the complete source for this project at:
712
The Editing Lifecycle Here is an overview of the stages that occur during editing a single node. A node enters edit +mode
A node that is being displayed by the RadTreeView control is selected and the user presses the F2 key to bring the node into edit mode. The RadTreeView control calls the BeginEdit() method and a new editor instance is initialized. It is available publicly through the ActiveEditor property in RadTreeView and is associated with the node that is about to be edited. The editor fires EditorInitialized event which you can handle according to your requirements. This event also provides you with the ability to change the input editor. A text box based editor appears for input.
The Enter key is pressed while the node is in edit mode. The editor determines if it wants to handle the keystroke. The editor instance performs the action it has defined for the Enter key. Typically this indicates that edit mode should be exited and any changes made during the edit session should be applied to the node Text property. In response to the action described in the previous step the EndEdit() method is called and the ValueChanged event is fired. The RadTreeView control sets the node Text property to the string representation of the editor Value property. The RadTreeView Edited event fires.
The code below shows these properties and events in play. Also notice the MouseDoubleClick event handler that also initiates editing without the user having to press the F2 key. In some cases you may want to compare new and old values for validation or display purposes.Save off the old value in the Editing event handler and get the new value during ValueValidating. [VB] Handling Editing Events Private Sub EditNodes_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load radTreeView1.AllowEdit = True End Sub Private _oldNodeText As String Private Sub radTreeView1_Editing(ByVal sender As Object, ByVal e As TreeNodeEditingEventArgs) Handles radTreeView1.Editing _oldNodeText = e.Node.Text ' disallow editing root nodes. If e.Node.Level = 0 Then e.Cancel = True lblStatus.Text = "You cannot edit a root node" End If End Sub
713
714
715
...but blank values are disallowed in the ValueValidating event. The Cancel argument is set to true, the old value is restored and an error message is displayed in the status strip.
On completion, the ValueValidating event fires and displays both new and old text values.
716
Within the treeview From the treeview to another treeview From the treeview to another control From another control to the treeview
Dragging within the treeview or between treeviews is handled by the RadTreeView control. Dragging to or from other non-telerik controls is handled by standard Windows form control drag methods.Dragging betweenRadControls for WinFormscanbe handled by the RadDragDropService. Three key RadTreeView properties enable Drag and Drop functionality:
AllowDragDrop enables the drag and drop functionality for a tree view control. Drag and drop functionality can also be used to reorder nodes within the tree. AllowDrop when true accepts data that the user drags onto it. This event is used to interact with drag and drop for standard Windows controls.
The AllowDragDropis completely automatic. Turn it on and you get enhanced dragging capabilities within the treeview and between treeviews. The selected node and child nodes are all moved to the target location with user interaction only. No code is required.
The "Janet Leverling" node is dropped onto the "Margaret Peacock" node, sothe "Janet Leverling" node becomes a child node of the "Margaret Peacock". This behavior is indicated by the fact that the dotted line which usually demonstrates where a node will be placed is gone.
717
The dragged node "Robert King" will be located as a sibling just above the "Steve Buchanan" node. The new position is indicated by a dotted line.
The dragged node"Janet Leverling" is dropped as a sibling just below the "Margaret Peacock" node. Again this behavior is indicated by a dotted line.
The same visual cues apply when dragging between tree views.
When dragging from the tree view to other controls you can use the standard Windows drag and drop events, or you can use the RadDragDropService when dragging between RadControls for WinForms.
718
You can find the complete source for this project at: \TreeView\<VB|CS>\DragAndDrop Form Appearance and Layout For the Drag and Drop Example First afew notes on how the form is setup. Add RadCommandBarto the form with two CommandBarToggleButtons. Set each buttonDrawText property totrue, remove the Image setting and set the Text properties to
AllowDragDrop
719
Feedback
A RadDock control is placed underneath the command bar and its Dock property is set to "Fill". The Dock control has a document window on the left and two tool windows in the upper and lower right side.Both toolwindows in RadDock has its CaptionVisible and TabStripVisible set to False and the TabStripVisible property of thedocument tab strip isset tofalse. The two RadTreeViews and one RadGridView are placed inside the windows. Your form should look like something similar to the following screen shot:
The Form Load Event Handler For the Drag and Drop Example The form Load event handler fills the tree view on the left named "tvLeft" with some data.The treeview and grid view drag drop service PreviewDragDrop and PreviewDragOver event handlers are hooked up to implement drag-and-drop from the treeview to the grid and vice versa. Remember that the drag-and-drop in the treeview and between treeviews is already enabled by the AllowDragDrop property. The RadGridView works in unbound mode simply by adding new GridViewTextBoxColumn to the Columns collection. [VB] Handling the Form Load Event For i As Integer = 0 To 19 tvLeft.Nodes.Add("Node " & i) Next ' configure treeview and hook up events
720
721
722
723
724
725
Dragging From Another Control to the RadTreeView For this purpose we are going to use the standard Windows Forms drag and drop functionality. AllowDrop enablesControl descendants to accept data dropped onto it to set the tvTopRight AllowDrop to true. This event can be used to allow interaction between standard Windows controls and RadTreeView. For example, to drag from a TextBox to the tree view. For the purpose of this example we are going to extend a bit the previous code. Add CommandBarTextBox to RadCommandBar and set its Text to "" and its MinSize property to 120,0. [VB] Dragging to RadTreeView Private Sub TextBox1_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles TextBox1.MouseDown TextBox1.DoDragDrop(TextBox1.Text, DragDropEffects.Copy Or DragDropEffects.Move) End Sub Private Sub tvTopRight_DragEnter(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles tvTopRight.DragEnter If e.Data.GetDataPresent(DataFormats.Text) Then e.Effect = DragDropEffects.Copy Else e.Effect = DragDropEffects.None End If
726
727
728
Checkboxes
Set CheckBoxes to True to display checkboxes or radio buttons next to each node in the tree. To check a node programmatically, use the CheckState property of RadTreeNode. The NodeCheckChanged event will fire whenever the user clicks a checkbox. Like RadCheckBox, "tri-state" checkboxes have checked/un-checked/indeterminate states. To get this behavior, set the tree view TriStateMode property to True. The "Install All" checkbox in the screenshot is displayed in an indeterminate state because the child "Help" node is unchecked.
Check boxes and radio buttons can be mixed in a single RadTreeNodeCollection. The RadTreeNode property that control the type of option element to be shown (check box or radio button) is CheckType.
729
[VB] Setting the CheckType ' display checkboxes next to nodes radTreeView1.CheckBoxes = True ' create a root node and set its CheckType to None Dim root As New RadTreeNode("Options") root.Expanded = True root.CheckType = CheckType.None ' create three nodes with radio buttons and select the second node Dim node1 As New RadTreeNode("Minimal") node1.CheckType = CheckType.RadioButton Dim node2 As New RadTreeNode("Install All") node2.CheckType = CheckType.RadioButton node2.CheckState = Telerik.WinControls.Enumerations.ToggleState.[On] Dim node3 As New RadTreeNode("Custom") node3.CheckType = CheckType.RadioButton ' add a checkbox node and select it Dim node4 As New RadTreeNode("Include Extras") node4.CheckType = CheckType.CheckBox node4.CheckState = Telerik.WinControls.Enumerations.ToggleState.[On] ' add nodes to the root node root.Nodes.Add(node1) root.Nodes.Add(node2) root.Nodes.Add(node3) root.Nodes.Add(node4) ' add root to the treeview nodes radTreeView1.Nodes.Add(root) [C#] Setting the ChecktType // display checkboxes next to nodes radTreeView1.CheckBoxes = true; // create a root node and set its CheckType to None RadTreeNode root = new RadTreeNode("Options"); root.Expanded = true; root.CheckType = CheckType.None; // create three nodes with radio buttons and select the second node RadTreeNode node1 = new RadTreeNode("Minimal"); node1.CheckType = CheckType.RadioButton; RadTreeNode node2 = new RadTreeNode("Install All"); node2.CheckType = CheckType.RadioButton; node2.CheckState = Telerik.WinControls.Enumerations.ToggleState.On; RadTreeNode node3 = new RadTreeNode("Custom"); node3.CheckType = CheckType.RadioButton; // add a checkbox node and select it RadTreeNode node4 = new RadTreeNode("Include Extras"); node4.CheckType = CheckType.CheckBox; node4.CheckState = Telerik.WinControls.Enumerations.ToggleState.On;
730
23.6 Summary
In this chapter you learned how to display, navigate and manage hierarchical data using the RadTreeView and RadBreadCrumb controls. You learned how to add, removeand move nodes programmatically, how to iterate nodes and how to locate nodes. You learned how to handle node editing. You saw how to implement drag and drop within the RadTreeView, how to drag and drop to other tree views and how to drag from the treeview to other controls. You learned how to attach context menus to particular nodes. You also learned about RadTreeView specific databinding issues including binding to self referencing data, binding to related data, writing to and from XML and load-on-demand.
731
24.1 Objectives
Learn how to createapplications with RazWizard. Learn the basicfunctionalityes of the control. Explore theways ofcustomization. Create s sample installation form.
24.2 Introduction
The RadWizard control will help you differentiate a complex process into separate steps and provide your users with the ability to govern the process upon their decisions. It is useful for creating installation, registration and other types of wizards. Each WizardPage contains panel where you can host the desired controls needed to create the required functionality. RadWizard supports both Wizard 97 and Wizard Aero specifications. The control provides the developers with predesigned Welcome, Completion and Internal pages. Follows is an example of a RadWizard Welcome page:
RadWizardElement encapsulates the UI representation and functionality of RadWizard. This element initializes the view of the control:
Wizard97View for the Wizard 97 mode. WizardAeroView for Wizard Aero mode.
Pages collection collection which contains Internal, Welcome and Completion RadWizard pages.
732
Page header element which is located above each page and contains elements for title text, header text and page icon. Command area element which is located below each page and contains command button Back (Wizard 97), Next, Cancel, Finish, and Help. Welcome image element which contains the image of the Welcome page. Completion image - element which contains the image of the Completion page. Top element element which contains the Back button of Wizard Aero view.
On the screenshots below, you can see the Welcome pages for both wizard mode with the described elements in them: Wizard97
Wizzard Aero
733
The Smart tag also allows you to add and remove Internal pages.
734
Add Internal, Welcome and Completion pages Remove pages Rearrange pages Customize page properties
735
Title = "RadControls for WinForms installation wizard" WelcomeImage = some appropriate image Icon = some appropriate image CustomizePageHeader = true Header = ""
5. One Wizard page is added by default. Click the Add drop down button and use the "Add Page" option to add two more pages.
736
6. On the first WizardPage set the title to "Choose installation type", on the second one to "Choose components to install" and the third to "Installation progress" . Remove the header settings for these pages. 7. Set the Title property for the WizardCompletionPage to "Installation Successful" and click OK to close the collection editor. 8. At this point your application should like like this.
737
9. Double click the form to create Load event handler. Center the image of the wellcome page by setting the WelcomeImageLayout of RadWizard control. [VB] Set the image alignment RadWizard1.WelcomeImageLayout = ImageLayout.Center [C#] Set the image alignment radWizard1.WelcomeImageLayout = ImageLayout.Center; 10. Go back to design time andadd RadLabel with Text "<html><p>Wellcome, </p><p></p><p>Thank you for choosing Telerik RadControls for WinForms.</p></html>" tothe welcome page. Set the MinSize to 0,50 and the font size to 12 pt. 11. Click next button to open the first WizardPage. Add two RadRadioButtons to the panel and RadLabel above them. 12. Set the following properties of RadLabel:
Text = "<html><p><span style="font-size: 14pt">Please choose installation type.</span></p><p></p><p></p><p></p><p><span style="font-size: 12pt"><strong>Full</strong> - to install all components of RadControls for WinForms.</span></p><p><span style="font-size: 12pt"><strong>Customize</strong> - lets you choose which components to install.</span></p></html>" MinSize = 0,100
13. Set the buttons Text to "Full" and "Customize" and the font size to 12pt.
738
14. Click next to navigate to the second WizardPage. Add RadLabel and eight RadCheckBoxes. Set the label font to 14 pt and the Text for the controls as follows:
radLabel1 = "Select features to install" radCheckBox1 = "RadControls for WinForms" radCheckBox2 = "Components" radCheckBox3 = "Demos" radCheckBox4 = "Visual Studio Extensions" radCheckBox5 = "Visual Studio 2005" radCheckBox6 = "Visual Studio 2008" radCheckBox7 = "Visual Studio 2010" radCheckBox8 = "Documentation"
15. Click next to navigate to the next page. Add RadLabel with Text "Installation progress" and font size 14 pt, and RadWaitingBar. 16. On the last page add label with text "<html><p>Congratulations, </p><p></p><p>RadControls for WinForms is successfully installed on your computer.</p></html>". 17. The wizard layout is ready now all that is left is to add the desired functionality to it. Lets handle the Help event of RadWizzard where we are going to open a webpage and the SelectedPageChanged event of the control where we will start the waiting bar, when needed. Additionally, we can handle the Cancel event of RadWizard to stop the application when the user wants and the Finish event to stop the application when
739
Private Sub radWizard1_Cancel(ByVal sender As Object, ByVal e As EventArgs)If RadMessageBox.Show("Are you sure that you want to stop the installation?", "", MessageBoxButtons.YesNo) = DialogResult.Yes ThenApplication.[Exit]()End IfEnd Sub Private Sub radWizard1_Finish(ByVal sender As Object, ByVal e As EventArgs)Application.[Exit]()End Sub [C#] Add functionality void radWizard1_Help(object sender, EventArgs e) { Process.Start(http://www.telerik.com); } void radWizard1_SelectedPageChanged(object sender, Telerik.WinControls.UI.SelectedPageChangedEventArgs e) { if (e.SelectedPage == wizardPage3) { radWaitingBar1.StartWaiting(); } else { radWaitingBar1.StopWaiting(); } } void radWizard1_Cancel(object sender, EventArgs e) { if (RadMessageBox.Show("Are you sure that you want to stop the installation?", "", MessageBoxButtons.YesNo) == DialogResult.Yes) { Application.Exit(); } } void radWizard1_Finish(object sender, EventArgs e)
740
741
742
743
744
24.5 Summary
In this chapteryou learnt how to create applications with RadWizard controland how to place controls on wizard pages and embedfunctionality. Also, few ways of customization were explored.
745
25.1 Objectives
Understand the basic tools and concepts used to style RadControls. Learn how to use themes and apply application level themes. Learn how to use the color blending feature.
25.2 Introduction
You have multiple routes to completelystyle all visual aspects of your application:
RadElement properties are loaded with eye-candy propertiesfor tweaking color gradient, multiple aspects of backgroundand border colors, gradient styles, angle and scale transforms. These can be reached through individual elements of RadControls in code or using the Element Hierarchy Editor (seethe Telerik Presentation Foundation chapter in "Accessing Elements" for more information). Predefined themes available in the ToolBox style your entire application with a unified look-and-feel in one shot. In addition, the ThemeResolutionService object queries for existing themes and lets you apply themes application wide. Use the Visual Style Builder to build your own theme codelessly. The Color Blending feature takes themes a step further by allowing you to apply new colors to existing themes.
746
At run-time, drill down through the tree of RadControl child elements when you need to access specific style related properties. [VB] Accessing RadElement Properties (TryCast(btnIncrease.ButtonElement.Children(0), FillPrimitive)).BackColor = Color.Crimson [C#] Accessing RadElement Properties (btnIncrease.ButtonElement.Children[0] as FillPrimitive).BackColor = Color.Crimson; Class selectors are used to apply the same customization to all elements that belong to the same class. This behavior is very similarto CSS class selectors. The "Class" referred to here is the ClassName property used to identify a RadElement. In the example below we're looking for elements with the ClassName "CalendarVisualCellElement". This chunk of code colors the text of every cell element in a RadCalendar. [VB] Using the ClassSelector Dim selector As New ClassSelector("CalendarVisualCellElement") For Each cellElement As CalendarCellElement In selector.GetSelectedElements (radCalendar1.CalendarElement) cellElement.ForeColor = Color.Purple Next [C#] Using the ClassSelector ClassSelector selector = new ClassSelector("CalendarVisualCellElement"); foreach (CalendarCellElement cellElement in selector.GetSelectedElements (radCalendar1.CalendarElement)) {
747
The unique set of color on this form comes from the image, so the best approach here is to extract bits of color from this image. Starting with the RadTitleBar, you can locate the underlying Fill primitive, click the BackColor..BackColor4 properties and use the eye dropper tool from the Color dialog.
Continue to "steal" colors for all the elements of the form until all the form colors work together. This method can be adapted to work with RadElements or used within the Visual Style Builder. This approach us relatively quick and lets you manually blend your control colors nicely with colors already in the application without needing to consult a creative designer.
748
Visual Property Value Precedence Properties that are set using the Element UI Editor at design time or modified at runtime take precedence andwill not be affected by settings in the theme.
If we add HTML tagged text to the title RadLabel in the earlier "Blue Sky Travel Planning" example you'll see a large "Papyrus" font using one of the image colors, a line break, then a slightly smaller font in another image color. [VB] Setting HTML Text lblTitle.Text = "<html>" + "<size=11><b><color=1,78,194><font=Papyrus>Blue Sky Travel Planning</b>" + "<br>" + "<size=10><color=72,173,229><font=Narkisim>Get where you're going" [C#] Setting HTML Text lblTitle.Text = "<html>" + "<size=11><b><color=1,78,194><font=Papyrus>Blue Sky Travel Planning</b>" + "<br>" + "<size=10><color=72,173,229><font=Narkisim>Get where you're going";
749
You can find the complete source for this project at: \Appearance and Styling\<VB|CS>\ElementsAndHTMLStyling
25.5 Themes
Themes supplied with RadControls for WinForms are available as standalone components, apart from the controls' assemblies. This simplifies the way themes are added to the application and improve application loading time.
To use Theme components, drag and drop from the VS Toolbox to the form. This adds a reference to the corresponding theme assembly in the project and displays the theme in the ThemeName drop-down of all Telerik controls on the form. As we've seen in earlier chapters, you can avoid the work of setting themes individually for each control by using the ThemeResolutionService to set the ApplicationThemeName: [VB] Setting ApplicationThemeName Private Sub ShapedForm1_Load(sender As Object, e As EventArgs) ThemeResolutionService.ApplicationThemeName = "Office2010Blue" End Sub [C#] Setting ApplicationThemeName private void ShapedForm1_Load(object sender, EventArgs e) { ThemeResolutionService.ApplicationThemeName = "Office2010Blue";
750
Set properties Using Visual Style Builder you can alter any property of any control. Because all Telerik controls are composed of primitives, this customization can be applied at a very fine level of detail. For example, if you are working with a RadMenu control you can easily change the background color used for submenu items without changing the color used for main menu items.
Inherit properties When working with complex controls in Visual Style Builder, you can inherit property values (such as colors, or fonts) from parent elements to child elements, or override them at the child element level.
Animate changes Visual Style Builder lets you animate changes in response to events, so that a property moves smoothly
751
Save themes Themes provide a way to reuse your work. Visual Style Builder can save themes to be applied consistently across controls, forms, or applications. This is similar to the way that cascading style sheets (CSS) works in Web applications. Suppose you have developed a custom theme for RadCommandBar that has particular colors, fonts, mouseover behavior, and so on. By saving these themes into an XML theme file (or a compressed .tssp file), you can apply it to every command bar control in your application. Using themes frees you from the repetitive work of setting properties on multiple controls.
752
After blending the orange and teal colorsthe entire form still has the "Desert" theme but the base color is Silver.
753
[VB] Applying Mulitple Color Blends Private Sub CommandBarDropDownList1_SelectedIndexChanged(ByVal sender As Object, ByVal e As Telerik.WinControls.UI.Data.PositionChangedEventArgs) Dim item As RadListDataItem = TryCast((TryCast(sender, RadDropDownListElement)).SelectedItem, RadListDataItem) Dim color As Color = CType(item.Value, Color) Dim currentTheme As Theme = ThemeResolutionService.GetTheme (ThemeResolutionService.ApplicationThemeName) currentTheme.AddColorBlend("BaseColor", Telerik.WinControls.HslColor.FromColor (color.Orange)) currentTheme.ThemeProperties("BaseColor") = Telerik.WinControls.HslColor.FromColor(color) currentTheme.AddColorBlend("CommandBarColor", Telerik.WinControls.HslColor.FromColor (color.FromArgb(170, 215, 218))) currentTheme.ThemeProperties("CommandBarColor") = Telerik.WinControls.HslColor.FromColor (color) End Sub [C#] Applying Mulitple Color Blends void commandBarDropDownList1_SelectedIndexChanged(object sender, Telerik.WinControls.UI.Data.PositionChangedEventArgs e) { RadListDataItem item = (sender as RadDropDownListElement).SelectedItem as RadListDataItem; Color color = (Color)item.Value;
754
25.8 Summary
This chapter briefly described the concepts used to style RadControls, provided a short description of the Visual Style Builder tool, discussed themes and the use of the ThemeResolutionService. You also learned how to use the Color Blending feature.
755
756
757
758
759
760
761
762
763
764
765
766
767