in
Forums
Blogs
Files
Devexpress.Com
ClientCenter
Support Center
DevExpress Channel

Windows Forms

  • Video: How to create a Master-Detail Report

    Check out this 4 minute screencast on how to create a master-detail report in XtraReports. This screencast uses the sample created in the last screencast. You can create unlimited master-detail levels in a single XtraReport. You don't need to use subreports with a separate master and detail datasource. Using a single datasource with native ADO.NET data relations, you can create a master-detail report. Just define a DataSet relation, then add a Detail Report band which includes this relation and you have a master-detail report without any writing any code.

    Be sure to pay attention to the coloring of the detail report bands' captions. XtraReports will color these captions according to their level at design time. This will make it instantly clear to you which detail level you're working with. Check out this screencast and learn how easy it is to create a master-detail layout in XtraReports.

    image

  • How to create a data aware XtraReport

    Here's a 5 minute screencast to show you how to create a data aware report using XtraReports. In a previous screencast, you can learn how to create a simple report in XtraReports. Now that you have your first report, you'll want to create reports with data from your database. So in this second screencast you'll learn how to create a report and bind the fields to an access database.

    The flexible data source support in XtraReports lets you use any data object supported by Visual Studio. And with 15 native XtraReports controls and the ability to render any 3rd party controls (charts, grids, calendars, etc.), you can create great reports with ease. Check out this screencast and learn some of the basics of XtraReports.

    image

  • How to Create a Simple 'Hello World' Report in XtraReports

    You may not know it but the XtraReports Suite is included in all of the DXperience Subscriptions. The XtraReports Suite can help you to create stunning reports. With Visual Studio integration and an end-user report designer, you can easily create and manage reports in your applications.

    If you've never used or seen XtraReports then check out the following short screencast which shows you how to create a simple 'Hello World' report.

    image

  • XtraLayout Control: New Features for Runtime Layout Customization

    In version 2008 vol 1, the XtraLayout control gives you greater flexibility for runtime layout customization. The control introduces three new features that allow you to make the UI more user-oriented.

    Implementing a Custom Customization Form

    You can now create your own Customization Form on the fly at design time, implementing custom logic or arranging customization controls in a custom manner. In addition to custom controls, with a few mouse clicks, you can add any of the standard controls supported by the default Customization Form to your own form:

    Implementing a Custom Customization Form

    These standard controls will be automatically integrated into the XtraLayout control's infrastructure. Here is an example of the custom Customization Form displaying the Button Panel, Hidden Item List and a custom 'Restore All' button:

    Implementing a Custom Customization Form

    See How to: Create custom customization form, for an example.

    Creating a Custom "Fixed" Layout Item

    There are a few predefined service layout items which are "fixed" to the Customization Form - Empty Space Item, Label, Separator and Splitter. These items are always available in the Customization Form, and when an end-user drags and drops them onto the XtraLayout control, they are cloned.

    In the current version, you can easily add custom "fixed" items to the Customization Form. For instance, you can create a "fixed" item that represents a LinkLabel control. So, when and end-user drags and drops this item onto the form, an instance of the layout item containing a LinkLabel is created and added to the layout.

    To implement a custom "fixed" item, create a LayoutControlItem class descendant and implement the IFixedLayoutControlItem interface.

    public class MyFixedLabelItem : LayoutControlItem, IFixedLayoutControlItem {
        public MyFixedLabelItem() {
            this.controlCore = new LinkLabel();
            this.linkCore = "www.devexpress.com";
        }
        #region IFixedLayoutControlItem Members
        string IFixedLayoutControlItem.CustomizationName {
            get { 
                return "DevExpress Link"; 
            }
        }    
        Control IFixedLayoutControlItem.OnCreate() {
            TextVisible = false;
            ((LinkLabel)controlCore).LinkClicked += label_LinkClicked;
            return controlCore;
        }
        //...
        #endregion
    }
    

    The only other thing to do is to register the new item in the XtraLayout control via the RegisterFixedItemType method. The image below demonstrates a custom DevExpress Link "fixed" item below the Splitter item:

    Creating a Custom Fixed Layout Item

    For a complete example, see How to: Create custom 'fixed' item.

    Filtering Properties in the Customization Form

    In customization mode, an end-user can modify specific properties of layout items via the Property Grid control embedded into the Customization Form. You can simplify the UI by filtering the Property Grid, i.e. providing access only to specific, main properties and hiding other, unimportant properties. And, with the current version, you can do this in a straightforward way.

    First, create a wrapper object inheriting the BasePropertyGridObjectWrapper class that publishes the properties to be listed in the Property Grid:

    public class MyLayoutControlItemPropertyWrapper : BasePropertyGridObjectWrapper {
        protected LayoutControlItem Item { 
            get { return WrappedObject as LayoutControlItem; } 
        }
        public string Text { 
            get { return Item.Text; } 
            set { Item.Text = value; } 
        }
        //...
    }
    

    And then, associate the wrapper object with a particular type of layout item:

    layoutControl1.RegisterCustomPropertyGridWrapper(typeof(LayoutControlItem), typeof(MyLayoutControlItemPropertyWrapper));
    

    Now, when selecting any layout item of this type, the Property Grid will list only the selected properties:

    Filtering Properties in the Customization Form

    Refer to How to: Specify which properties to display in the Property Grid when selecting layout items, for a complete example.

  • XtraReports Screencast: Create a Cross-Tab Report

    <Update May 20, 2008>Check out the online demo to see a live example of a cross-tab report.</Update>

    Cross-Tab reports can be a great way to show summaries of data. What is a Cross-Tab report? As Oliver's says: "A cross table is basically the result of transposing some data and using one of the fields for a second dimension."

    The Problem

    Often you have sequential data like a list of orders. For example, orders that have dates and also a reference to a customer. In a linear report, you can group either by dates or by customers. And while you can also group by both, the result isn't what you want because you have to decide on the order of the grouping. So it would be great to have the dates in the row headers and the customers in column headers, or the other way round.

    The Solution

    Creating the SQL statement for a pivot table can be a headache. Why not simply drop a component on a form, point to your datasource and create the report using a designer? XtraReports makes it easy to create Cross-Tab reports. Check out this short 2 minute screencast which shows the simple drag-and-drop style to creating a complex Cross-Tab report.

    image

    You may also find the written version of this demo useful. If you want to read more about Cross-Tab in WinForms, then check out Oliver's blog post on this topic.

  • Are you ready for Valentine's Day?

    [Update: v2007.3.7 is now available through your Client Center account]

    Your application can be ready with the new skin coming in the next minor release (v2007.3.7). The team has cooked up something special just for you and for the month of February. Here is just a hint of what's going to be coming out very soon (Click image for larger version):

    image

    You'll be treated to a special registration screen as well:

    clip_image002

    You may find these knowledgebase/help articles useful for working with skins:

    So what do you think of the new skin?

  • New Layout View for XtraGrid

    Getting rid of detail forms from your projects!

    As you know, we have a great WinForms control for representing tabular data called the XtraGrid. It neatly solves various tasks for displaying, editing, and analyzing record-oriented data. Oftentimes though, the issue with displaying tabular data is the tabular layout itself. This format rapidly becomes user-unfriendly when you need to show a large number of columns. Take a look at the following image from the designer:

    Even if you manage to get all the columns into the view by setting the ColumnAutoWidth option to false, there is still a comprehension problem with the simultaneous access to all the column at once:

    Despite the availability of the AdvancedBandedGrid View, there is still no perfect way to have simultaneous access to all the data for a large record. An end-user can certainly see that data all at the same time but, due to the column headers and cells in a row being displayed across multiple lines, it's not really easy for end-users to find column headers that match specific cells:

    Before version 2007.3, simultaneous access to all of the data for a given record could be done by using a Card View or by creating an external detail form for data viewing and editing. Unfortunately these solutions do have their drawbacks: the CardView arranges fields in a single column and doesn't support other layouts; and creating a detail form can be challenging and time-consuming.

    With these considerations in mind, we've introduced a new View for the XtraGrid control, LayoutView, which is a straightforward way to display and edit a large number of columns at a time.

    There is no longer any need to create external detail forms to edit data since the LayoutView supports numerous field layouts and it's embedded into the XtraGrid control. With the LayoutView, you can easily implement user-friendly interfaces, even if there are dozens of columns in a record:

    Records in the LayoutView are represented as cards, but without the limitations of the original CardView. In the image above, for example, the Single Record mode is enabled such that a single card is displayed at a time. In addition to this mode, the LayoutView supports other card layouts: arranging cards in rows, columns, and the fun carousel mode.

    Please refer to our online documentation to learn more about the new View: Layout View.

  • XtraSpellChecker: Dictionaries

    Summary

    The XtraSpellChecker requires at least one dictionary type be defined. Which dictionary do you use? Where do you find the best dictionaries? Read below to find out.

    The SpellChecker component uses special spell checking algorithms which require a dictionary to provide the list of words and/or rules. At a minimum, one of the four dictionary types must be defined for the SpellChecker. Therefore, to add spellchecking to your project, you need to:

    • Choose the most appropriate dictionary type (Simple, ISpell, OpenOffice)
    • Add it to your application for every particular language (culture) you want to support.
    • Add a custom dictionary for every language if you want allow end-users to add custom words.

    Dictionaries can be shared by several SpellChecker components. You can add them to the SharedDictionaryStorage and then set SpellChecker.UseSharedDictionaries to true. This helps avoid time-consuming operations on loading dictionaries and maintain a single custom dictionary for all SpellChecker components in your application.

    You can try all the samples below for yourself. Just download the following file and open this project in Visual Studio 2005: SpellCheckerExample.Zip


    Simple Dictionary

    This dictionary type lists words in a plain text file where each line contains only one word. To use this dictionary, manually prepare a text file (or export any existing dictionary to a plain text file).

    The following code demonstrates how to create the SpellCheckerDictionary component at runtime. It also shows how to use an alphabet file containing all letters in your preferred language:

    standardDictionary = new SpellCheckerDictionary();
    standardDictionary.Culture = new CultureInfo("en-US");
    standardDictionary.AlphabetPath = @"\Dicts\Standard\EnglishAlphabet.txt";
    standardDictionary.DictionaryPath = @"\Dicts\Standard\American.txt";
    

    ISpell Dictionary

    An ideal dictionary would contain all the words of a given language. However, it's much smaller and more effective to split the dictionary into several parts (depending on the language). For example, in several Indo-European languages, including English, words are derived from the base by adding affixes - prefixes or postfixes. So the size of the dictionary can be greatly reduced if the base words, affixes and the rules for adding affixes to base words are placed into separate files. The complete list of words could be built in-place, when necessary. This technique proves its effectiveness especially for synthetic languages (rich in verbal and inflective forms) – Lithuanian or Russian, for example.

    The ISpell dictionary is based upon this approach that includes the base words and affixes. Physically it's represented by the Alphabet file - *.txt, the Affix file - *.aff, and the Base Words file - *.xlg or *.hash. (Note: XtraSpellChecker doesn't provide support for compressed *.hash files but you may use *.xlg files).

    ISpell dictionaries are mostly developed by enthusiasts all over the world, and you may freely find them for different languages on the Web. For example, the English dictionary can be found at ftp://ftp.tue.nl/pub/tex/GB95/ispell-english.zip. Note also that due to being developed by different people, each ISpell dictionary may be redistributed under its specific license agreement; however most of them are free.

    You can get more information about ISpell dictionaries on the following on-line resources:
    http://en.wikipedia.org/wiki/Ispell
    http://www.lasr.cs.ucla.edu/geoff/ispell.html

    The following code demonstrates how to create the SpellCheckerISpellDictionary dictionary at runtime:

    iSpellDictionary = new SpellCheckerISpellDictionary();
    iSpellDictionary.Culture = new CultureInfo("en-US");
    iSpellDictionary.AlphabetPath = @"\Dicts\ISpell\EnglishAlphabet.txt";
    iSpellDictionary.DictionaryPath = @"\Dicts\ISpell\american.xlg";
    iSpellDictionary.GrammarPath = @"\Dicts\ISpell\english.aff";
    

    Open Office Dictionary

    The Open Office dictionary is similar to ISpell, since it also generates the entire word list based on the Affix file - *.aff, and the Base Words file - *.dic. But note that this standard provides different rules for the Affix file than ISpell, so you can't use the same Affix files for both dictionaries.

    In general, Open Office dictionaries are word rich and contain less mistakes than ISpell since they are developed by more people. The dictionaries and affix files used are a part of the OpenOffice.org project and can be download from here: Dictionaries page.

    The following code demonstrates how to create the SpellCheckerOpenOfficeDictionary component at runtime:

    openOfficeDictionary = new SpellCheckerOpenOfficeDictionary();
    openOfficeDictionary.Culture = new CultureInfo("en-US");
    openOfficeDictionary.DictionaryPath = @"\Dicts\OpenOffice\en_US.dic";
    openOfficeDictionary.GrammarPath = @"\Dicts\OpenOffice\en_US.aff";
    

    Custom Dictionary

    Custom dictionaries are intended to store user additions (words that are considered by users as "correct"). For example, after a SpellChecker has a custom dictionary for the current Culture, an end-user is able to click on the Add button and add this word to the currently available custom dictionary. The other dictionary types don't support this feature.

    Adding a word to a custom dictionary 

    Also, a set of words in a custom dictionary may be manually changed by an end-user by invoking the Custom Dictionary dialog via the Edit button on the Spelling Options form.

    Modifying a custom dictionary

    The following code demonstrates how to create the SpellCheckerCustomDictionary component at runtime:

    customDictionary = new SpellCheckerCustomDictionary();
    customDictionary.Culture = new CultureInfo("en-US");
    customDictionary.AlphabetPath = @"\Dicts\Custom\EnglishAlphabet.txt";
    customDictionary.DictionaryPath = @"\Dicts\Custom\CustomEnglish.dic";
    

    Note: A custom dictionary is overwritten by the XtraSpellChecker every time a new word is added to it, or it's manually changed by an end-user. Therefore this file must not be set to read-only.

    All dictionaries are added to the Dictionaries collection of the SpellChecker. You can add multiple dictionaries of the same type to this collection. For example, you may add different dictionaries for different languages to a single SpellChecker, and then the SpellChecker chooses appropriate dictionaries according to its current Culture.

    Have any other questions about dictionaries? Need help finding one? Please drop by the XtraSpellChecker forum to ask or just to learn more.

  • XtraSpellChecker: Check Spelling as You Type

    Did you know that the XtraSpellChecker Suite can check spelling as you type? Just like in MS Word or Outlook.

    Enabling this feature is a breeze, just set one property and call one method:

    Set the SpellCheckMode property to AsYouType:

    spellChecker1.SpellCheckMode = SpellCheckMode.AsYouType;
    

    Then call the SpellChecker.Check method, and you're set:

    spellChecker1.Check(memoEdit1);
    

    After enabling the "check as you type" feature, red curves are displayed under misspelled words. Words are underlined to show that the spell checker doesn't recognize them.

    Check spelling as you type

     

    The appearance of the red curves are fully customizable. If you prefer Blue then set the SpellChecker.CheckAsYouTypeOptions.Color property:

    Set the CheckAsYouTypeOptions property

    To correct a misspelled word just right-click on the misspelled word and you'll get a list of suggested words from the dictionary:

    Blue lines

    Parts [1] and [2] of this series showed the XtraSpellChecker's other capabilities. In a future post, you'll see how different dictionaries can be used to make XtraSpellChecker conform to your needs.

    Are you curious about other XtraSpellChecker features?

    Which features are your favorites?

    Please leave a comment below and let me know. Thanks!

  • XtraSpellChecker: How to Enable Spell Checking

    In a previous post, you learned about the XtraSpellChecker component. Now let's dig deeper and see some samples to enable spell checking in your application.

    Runtime Samples

    The following examples will show you how to use the Check and CheckContainer methods in different ways. These methods allow you to check the spelling of various controls.

    Check a TextBox

    To check the text of a TextBox control use the following code. You can bind this method to just about any event such as a button click:

    private void simpleButton1_Click(object sender, EventArgs e) {
        spellChecker1.Check(textBox1);
    }
    

    Check any text-aware control

    The Check method can check text from any control. Just pass the text value to the Check method and you'll be returned the text processed by the spell-checker engine.

    private void simpleButton1_Click(object sender, EventArgs e) {
        myTextControl.Text = spellChecker1.Check(myTextControl.Text);
    }
    

    Check all controls on a form

    If you want to check all text-aware controls on a container then just call the CheckContainer method:

    private void simpleButton1_Click(object sender, EventArgs e) {
        spellChecker1.CheckContainer(this);
    }
    

    Use a Hotkey like F7

    One of the default hotkeys for Microsoft Office is F7 for spell checking. You can provide the same experience and familiarity for your users by binding the F7 key for your form to start spell checking. Below, the F7 key is bound to an XtraGrid Control:

    private void gridControl1_EditorKeyDown(object sender, KeyEventArgs e) {
        if (e.KeyCode == Keys.F7 && e.Modifiers == Keys.None)
            DoCheck();
    }
    
    protected virtual void DoCheck() {
        spellChecker1.Check(GetActiveControl());
    }
    
    private Control GetActiveControl() {
        return gridControl1.FocusedView.IsEditing ? 
            gridControl1.FocusedView.ActiveEditor : ActiveControl;
    }
    

    Checking via the context menu

    Right-clicking to check text is very popular as well. You can easily provide this for certain controls like a Memo control by calling the SpellChecker.SetShowSpellCheckMenu method:

    private void MemoEditForm_Load(object sender, EventArgs e) {
        spellChecker1.SetShowSpellCheckMenu(memoEdit1, true);
    }
    

    You now have the "Check Spelling" menu item added to the bottom of the control's context menu:

    The "Check Spelling" menu item

    Viola, your text-aware controls can now easily be spell checked!

    You can try all the samples above for yourself. Just download the following file and open in Visual Studio 2005: SpellCheckerExample.Zip

    Are you curious about anything else with the XtraSpellChecker? Just drop me a note or comment here. Thanks.

  • XtraSpellChecker: A simple but powerful spell checker for WinForms applications

    You can easily provide spell checking capabilities to your WinForms applications with XtraSpellChecker.

    image 

    Compatible Controls

    The Spell Checker can check the spelling of almost any control that has a Text property. Some examples of supported controls:

    • System.Windows.Forms.TextBox
    • DevExpress.XtraEditors.TextEdit
    • DevExpress.XtraEditors.MemoEdit
    • System.Windows.Forms.RichTextBox (Next Release, 2007 vol 3)

    The XtraSpellChecker can check with our WinForms grids (e.g. XtraGrid, XtraVerticalGrid, etc.) as well since they contain TextEdit and MemoEdit editors for their cells.

    You can also check any arbitrary text by passing it to the Check method as a parameter.

    Components To Use

    The main component, which provides all spell checking abilities, is the SpellChecker. The clip_image001SpellChecker is located in the “DX: Win.v7.2” tab in the Visual Studio toolbox. You can also create it at runtime:

    using DevExpress.XtraSpellChecker;
    
    SpellChecker spellChecker1 = new SpellChecker();
    

    You can now set some it's properties like the default for Culture property. This specifies culture settings (the symbols encoding, language and phonetic specifics):

    spellChecker1.Culture = new System.Globalization.CultureInfo("en-US");
    

    Please note that if you use several SpellChecker components and one dictionary, then a clip_image002SharedDictionaryStorage component is required.

    Enable Spell Checking

    The SpellChecker component provides two methods to check the spelling for controls: Check() and CheckContainer().

    The following code demonstrates how to pass a text to the Check method:

    private void simpleButton1_Click(object sender, EventArgs e) { 
       textBox1.Text = spellChecker1.Check(textBox1.Text);
    }
    

    The Dictionaries

    The SpellChecker component uses special spell checking algorithms. Every algorithm requires a dictionary, which provides the list of words and/or rules to generate this list. To enable spell checking in your application you need to define at least one dictionary.

    First choose which dictionary best meets your requirements. The XtraSpellChecker suite supports four basic dictionary types.

    • Simple
    • ISpell
    • Open Office
    • Custom

    Dictionaries can be defined both at design and runtime. For example, at runtime you can create an ISpell dictionary:

        iSpellDictionary = new SpellCheckerISpellDictionary();
       iSpellDictionary.Culture = new CultureInfo("en-US");
       iSpellDictionary.AlphabetPath = @"\Dicts\Dicts\ISpell\EnglishAlphabet.txt";
       iSpellDictionary.DictionaryPath = @"\Dicts\Dicts\ISpell\american.xlg";
       iSpellDictionary.GrammarPath = @"\Dicts\Dicts\ISpell\english.aff";
    

    You'll see each of these dictionaries described in more detail in an upcoming post.

    Download and try the XtraSpellChecker today. The XtraSpellChecker Suite is part of the DXperience Professional and Enterprise Suites. Currently, the XtraSpellChecker Suite is for Windows Forms only. However, an ASP .NET version is being developed.

    Are you using the XtraSpellChecker in your apps? I'd love to hear your stories with this amazing little control.

  • XtraGrid/ExpressQuantumGrid Users: Is QA testing important to you?

    Are you using the XtraGrid or ExpressQuantumGrid in your applications? Do you wish these grids were easier to test for quality assurance?

    You'll be happy to know that creating and running tests on these grids has just gotten easier. AutomatedQA has announced extended support for grid controls including the XtraGrid and ExpressQuantumGrid.

    In TestComplete 6, the support for grid controls has been dramatically improved. TestComplete 6 includes specific program objects that provide scripting access to the most popular grid controls:

    Developer Express XtraGrid
    Developer Express QuantumGrid

    These program objects provide scripting access to grids’ cells and contain methods that let you simulate user actions over the grid windows: clicking cells, expanding and collapsing rows, sorting data and so on.

    Unlike previous versions of TestComplete, version 6 records scripts using these methods, which makes the script more readable and configurable.

    You can find more information on their What's New page and the corresponding blog entry where you can download the beta.

    You might want to check out the several articles they've written on testing the XtraGrid Suite and ExpressQuantumGrid Suite.

     

  • Printing and Exporting Improvements in v6.2

       In version 6.2 we have extended and improved the exporting and printing capabilities of the XtraGrid, XtraTreeList and XtraLayoutControl. Now the XtraGrid and XtraTreeList controls can be exported to various formats, including RTF and MHT. Additionally, the XtraLayoutControl provides full printing and export support. 
       Table 1 and Table 2 below contrast the printing and export features supported in v6.1 and v6.2 respectively.

    Table 1. Printing and exporting support in v6.1

     

    XtraLayoutControl

    XtraTreeListControl

    XtraGridControl

    Printing support

    -

    +

    +

    Export to Excel

    -

    -

    +-

    (images were not exported)

    Export to TXT

    -

    -

    +

    Export to RTF

    -

    -

    -

    Export to MHT

    -

    -

    -

    Export to PDF

    -

    +-

    (text data was exported as graphics)

    +-

    (text data was exported as graphics)

    Export to HTML

    -

    -

    +

    Export to Image

    -

    +

    +

    Table 2. Printing and exporting support in v6.2

     

    XtraLayoutControl

    XtraTreeListControl

    XtraGridControl

    Printing support

    +

    +

    +

    Export to Excel

    +

    +

    +

    Export to TXT

    +

    +

    +

    Export to RTF

    +

    +

    +

    Export to MHT

    +

    +

    +

    Export to PDF

    +

    +

    +

    Export to HTML

    +

    +

    +

    Export to Image

    +

    +

    +

    In v6.1 the XtraTreeListControl and XtraGridControl exported their cell values to PDF files as graphics, so it was impossible to select text or perform a text search in PDF viewers. In addition, the XtraGridControl didn't export images in XLS format. In version 6.2 we've removed these limitations.
    The XtraLayoutControl v6.2 can now be printed and exported to various formats using the XtraPrinting Library. This enables you to use the XtraLayoutControl to:
    - create forms that look like printed forms, edit and print them;
    - create multiplatform (win + web) applications using HTML export;
    - integrate your solution with MS Office using RTF and XLS exports.

  • XtraTreeList feature preview: business objects binding

       The XtraTreeList is a powerful control for visualizing and editing hierarchical data. The XtraTreeList v6.1 can be bound to any standard datasource or an IList instance, or it can be used in unbound mode. In v6.1 unbound mode was presented by the AppendNode() method. We have discovered that unbound mode is often used for visualizing/editing the structure of business objects. But it takes a lot of time to get your objects shown in the XtraTreeList since you need to write a lot of code which constructs the desired tree by repeatedly calling AppendNode().

      In XtraTreeList v6.2 we decided to implement binding of business objects. You will be able to write the following code:

    myTreeList.DataSource = myBusinessObject;

    How does business objects binding work? Take a look at the picture below.

       Since the TreeList does not know the business object structure it fires events that will be processed in the user code. These events are InitChildren and InitCell. On InitChildren your code should return the children list via InitChildrenInfo.Children. On InitCell your code should return the required cell's value via InitCellInfo.CellData.
    Another approach is to get the business object's structure via the interface. This idea is illustrated in the following diagram.

    Well, let's see how business object binding saves you time. We have rewritten the TreeListExplorer demo, so let's compare the code that creates the tree.

    Old version (append node approach - you can find it in the v6.1 TreeListExplorer demo sources)

      
       private bool HasFiles(string path) {
        string[] root = Directory.GetFiles(path);
        if(root.Length > 0) return true;
        root = Directory.GetDirectories(path);
        if(root.Length > 0) return true;
        return false;
       }
       private void InitFolders(string path, TreeListNode pNode, CheckState check) {
       treeList1.BeginUnboundLoad();
       TreeListNode node;
       DirectoryInfo di;
       try {
        string[] root = Directory.GetDirectories(path);
        foreach(string s in root) {
         try {
          di = new DirectoryInfo(s);
          node = treeList1.AppendNode(new object[] {s, di.Name, "Folder", null, di.Attributes, check}, pNode);
          node.HasChildren = HasFiles(s);
          if(node.HasChildren)
           node.Tag = true;
         } catch {}
        }
       }
       catch {}
       InitFiles(path, pNode, check);
       treeList1.EndUnboundLoad();
      } 
    
      private void InitFiles(string path, TreeListNode pNode, CheckState check) {
       TreeListNode node;
       FileInfo fi;
       try {
        string[] root = Directory.GetFiles(path);
        foreach(string s in root) {
         fi = new FileInfo(s);
         node = treeList1.AppendNode(new object[] {s, fi.Name, "File", fi.Length, fi.Attributes, check}, pNode);
         node.HasChildren = false;
        }
       } catch {}
      }
      
      private void InitDrives() {
       treeList1.BeginUnboundLoad();
       TreeListNode node;
       try {
        string[] root = Directory.GetLogicalDrives();
        
        foreach(string s in root) {
         node = treeList1.AppendNode(new object[] {s, s, "Logical Driver", null, null, CheckState.Unchecked}, null);
         node.HasChildren = true;
         node.Tag = true;
        }
       } catch {}
       treeList1.EndUnboundLoad();
      }
      private void InitRoot() {
       if(!toolBar1.Buttons[0].Pushed)
        InitFolders(Directory.GetDirectoryRoot(Directory.GetCurrentDirectory()), null, CheckState.Unchecked);
       else
        InitDrives();
      }
    
      private void treeList1_BeforeExpand(object sender, DevExpress.XtraTreeList.BeforeExpandEventArgs e) {
       if(e.Node.Tag != null) {
        Cursor currentCursor = Cursor.Current;
        Cursor.Current = Cursors.WaitCursor;
        InitFolders(e.Node.GetDisplayText("FullName"), e.Node, (CheckState)e.Node.GetValue("Check"));
        e.Node.Tag = null;
        Cursor.Current = currentCursor;
       }
      }
     }
    

    New version (business objects binding approach)

    private void treeList1_InitCell(object sender, DevExpress.XtraTreeList.InitCellInfo e) {
       DirectoryInfo di = new DirectoryInfo((string)e.Node);
       if (e.Column == treeListColumn1) 
         e.CellData = di.Name;
       if (e.Column == treeListColumn2) {
        if (!IsFile(di))
         e.CellData = "Folder";
        else 
         e.CellData = "File";
       }
       if (e.Column == treeListColumn3) {
        if (IsFile(di)){
         e.CellData = new FileInfo((string)e.Node).Length;
        }
        else e.CellData = null;
        
       }
      }
    
      private void treeList1_InitChildren(object sender, DevExpress.XtraTreeList.InitChildrenInfo e) {
       if (loadDrives == false){ // create drives
        string[] root = Directory.GetLogicalDrives();
        e.Children = root;
        loadDrives = true;
       }
       else {
        try{
         string path  = (string)e.Node;
         string[] dirs = Directory.GetDirectories(path);
         string[] files = Directory.GetFiles(path);
         string[] arr = new string[dirs.Length + files.Length];
         dirs.CopyTo(arr,0);
         files.CopyTo(arr,dirs.Length);
         e.Children = arr;
        }
        catch { e.Children = new object[]{}; }
       }
      }
    

       Let's analyze the differences. 

    • The code was reduced by at least half and is easier to read and understand.
    • There are no for loops in the tree's construction code.
    • You do not need to handle the BeforeExpand event since child nodes are initialized by demand when a parent is expanded
    • Like in the append node approach, you can control the data displayed by the TreeList based upon runtime conditions.

       This new business object binding feature will be available in v6.2. We have implemented both event-based and interface-based approaches.

     

  • Visual inheritance support for complex controls.

    As all of you probably know, when .NET was released, Microsoft introduced support for visual inheritance - VI. There are a number of articles on the web which praise VI, but this blog entry discusses its limitations when used with complex controls. To do so, we'll start by creating a new control which contains a public collection.

    public class MyControl1 : Control {
            Collection items;
            public MyControl1() {
                items = new Collection();
            }
            [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
            public Collection Items {
                get { return items; }
            }
    }
    }

    Start VS2005. Create a new windows application, and add the above class to it. After rebulding, you will see MyControl1 at the top of the toolbox. Add MyControl1 to form1, and set MyControl1.Modifiers to public and take a look at the Items collection

    Note that we can change it without any limitations. Now create a descendant of form1 successor via visual inheritance(Project-> Add -> NewItem -> Inherited Form). Let’s look at the Items collection in the descendant

    We can not change collections in the successor, since this is disabled by Microsoft. What is the reason for this? Collections cannot be serialized correctly in VI descendants.

    Now lets talk about complex controls. By complex I mean a control which contains a public collection that should serialize correctly at designtime. VI is a powerful thing for rapid UI development but you should take into account the limitation's of collection serialization. Here are a set of recomendations you should follow when creating VI descendants of DX controls. 

    1. There are no known limitations for XtraEditors when using VI
    2. You should not change the XtraLayoutControl's layout in a descendant (all changes will be lost!) A workaroud is to split the form’s layout into several parts and create a separate XtraLayoutControl for each one. This approach is shown in the XtraLayoutMainDemo. The topmost part (which contains Save/Load buttons) for all demo modules is inherited.
    3. In VI descendants Moving or Removing inherted columns in the collection can cause problems, you can only safely Add columns to the XtraGridControl. But there are no limitations on changing the properties of existing columns.
    4. You cannot remove inherited items from XtraBars.
    5. VI for inherted collections is not supported by the TreeList, VerticalGrid, PivotGrid, XtraSheduler and XtraCharts.  

    The rules above can be summarized by a single general rule: Changing collections in VI descendants leads to problems and you should avoid changing collections in descendants.

    Let's now discuss some typical examples of correct and incorrect usage of VI.

    XtraBars
    Incorrect:
    Arrange item links on toolbars in the successor.
    Correct: Add all bar items in the base control, place them on toolbars programmatically.
    XtraGrid
    Incorrect:
    Customize XtraGrid in the base form.
    Correct: Place an empty XtraGrid on the base form and bind it to data and create columns in successors.
    XtraLayout
    Incorrect:
    Customize layout in the successors.
    Correct: Split the form's layout into the several logical square segments and create a separate XtraLayout control for each of them. Customize each layoutControl in the form where is it was created.

More Posts Next page »
Copyright © 1998-2008 Developer Express Inc.
ALL RIGHTS RESERVED