Blogs

Paul Kimmel's Blog

June 2009 - Posts

  • Re-registering DevExpress Controls with Visual Studio

         

    Every once in a while some confluence of events causes my Developer Express controls to disappear from the Visual Studio toolbox. I am not going to be an apologist for this, but support are having problems reproducing this problem. (If any of you have any hints they’d be appreciated by all.) I think it is annoying and would like to see the problem permanently resolved, but if it happens to you here is what you can do to quickly and painlessly re-register the controls with Visual Studio.

    To re-register DevExpress controls with Visual Studio click Start|All Programs|Developer Express v2009 vol1|Components|Tools|ToolboxCreator.exe (clicking on the ToolboxCreator.exe executable). All other variations of running this command results in the dreaded error dialog (see Figure 1). Make sure you close Visual Studio before running the ToolboxCreator.exe utility.

     

    image 
    Figure 1: Avoid this command and re-register your Developer Express controls with the ToolboxCreator utility.

  • Implementing a Class in JavaScript

         

    JavaScript is most commonly used for client-side Web programming. You can use JavaScript for other things, for example, it is used with Visual Studio Add-Ins and wizards, but generally we think of JavaScript as a Web technology. JavaScript is syntactically pretty close to the C programming language, but JavaScript is object based. JavaScript supports functions, data, and objects, and you can implement your own classes. You can dynamically define an object and add properties to JavaScript objects simple by referring to the property as a member. You can also statically define a class (at design and add fields, properties, and functions) and then create instances of that class and interact with those members in your code. Obviously the reason for defining JavaScript classes is valid for the same reason you define VB or C# classes; classes help manage state and organize your code.

    Dynamically Defining Object Properties and Functions

    You can add properties and functions on the fly. By literally creating an instance of the Object type and using the member of (. operator) syntax the name on the right side of the dot operator becomes a dynamic member. For example, if you instantiate a variable named Person as a type of Object and refer to a property then the property exists. Here is an example:

    var Person = new Object();
    Person.FirstName = “Paul”;

    (Its sort of weird, but) by referring to FirstName it becomes a bonafide property of Person. You can use the same approach to dynamically assign a function to Person too. Suppose for example you have a function Print—Print will just display the alert dialog. You can make Print a member of Person by assigning the function Print to a dynamically used member function. Listing 1 contains a block of script that dynamically adds properties and a function Print to object Person. Notice that the Print function can use the reference-to-self object this to access FirstName and LastName because Person.Print = Print makes the Print function a member of Person. (You can use the QuickWatch window to see that this refers to Person and shows the members FirstName, LastName, and Print.

    Listing 1: A dynamic class is created by simply using names as if they were statically defined as members of the class.

    <script type="text/javascript">

    var Person = new Object();
    Person.FirstName = "Paul";
    Person.LastName = "Kimmel";
    Person.Print = Print;

    Person.Print();

    function Print() {
      debugger;
      alert(this.FirstName + ' ' + this.LastName);
    }

    </script>

    image
    Figure 1: Use the QuickWatch when the debugger statement is hit to see that this refers to Person and Person contains the dynamically used members.

    Dynamically adding properties is a useful technique for returning data from a modal dialog. In script window.showModalDialog returns a single value. The way to return multiple values is to dynamically create a composite value—a dynamic object—and return the composite value. For example, if a modal dialog supported editing properties like first and last name then you could return the Person object from the showModalDialog function.

    Defining JavaScript Classes

    You can statically define JavaScript classes. The notation for a statically defined class is the function notation. (The outer function is treated as the constructor function.) The difference between a function and a class exists when a function contains nested properties and functions. Then, the function implicitly is playing the role of a class. For example, to retrofit the code in Listing 1 to a class rework the code as shown in Listing 2.

    Listing 2: A Person class; classes in JavaScript use the function notation.

    function Person() {
        this.FirstName = “”;
        this.LastName = “”;
        this.Print = print;
        function print() {
          debugger;
          alert(this.FirstName + ' ' + this.LastName);
        }
      }

    By declaring this.FirstName and this.LastName and initializing them they become part of the Person class. The statement this.Print assigned to print (note the case difference) then the print function is accessible. Listing 3 demonstrates how to create an instance of the Person object, assign values to the properties, and invoke the function. If you place a debugger statement right after the var aPerson statement and use the QuickWatch you will see that the Person object contains FirstName, LastName, and Print.

    Listing 3: Using the Person class.

    var aPerson = new Person();
    aPerson.FirstName = "Paul";
    aPerson.LastName = "Kimmel";
    aPerson.Print();

    JavaScript OO is a little awkward if you compare it to a more fully developed OO language like C#. Using a property makes it a member, adding a function and assigning it to a name makes it an accessible member, and the wonkiest bit of all is the constructor function as class. The upside is that writing code like this will help you organize your JavaScript, maintain state, and promote reusable code and good housekeeping.

  • Debugging with Tracepoints

         

    When you press F9 in Visual Studio—or select Debug|Toggle breakpoint—a little red circle representing the breakpoint is placed in the left-hand column of the editor window adjacent to the line of code containing the break. Breakpoints used to be a literal interrupt 0x03 inserted in the code quietly. I am not sure if that is how Visual Studio ultimately does it way underneath the covers, just thought I’d throw that bit if Jeopardy trivia out there.

    A variation on the Breakpoint is called a Tracepoint. A Tracepoint is represented as a red diamond in the left hand margin. You can insert a Tracepoint by right-clicking on a line of code and selecting Breakpoint|Insert Tracepoint. This option is the same as clicking an existing Breakpoint in the left margin and selecting the When Hit Count… (You can also access this feature from the Breakpoints window.) When you insert a Tracepoint the When Breakpoint Is Hit dialog is displayed (see Figure 1). If you click Print a message then you can use pre-defined constants like $FUNCTION or $TID to write trace information to the Output window. $FUNCTION represents the current function, and $TID is the thread id. (Other special keywords include $CALLER, $ADDRESS, $CALLSTACK, and $PID (process id). In the same dialog—see Figure 1—you can leave Continue execution checked, and the ‘When Breakpoint is Hit’ feature will act just like a Debug.Trace statement in your code. The final thing you can do is check Run a macro. Run a macro has a dropdownlist of existing macros you can choose from to run when the Tracepoint is hit. Visual Studio also has a Macro IDE, and you can code your own macros. If you write a macro then your macro (or macros) will also show up in the dropdownlist for the Run a macro section.

    image
    Figure 1: The Tracepoint dialog is part of the Visual Studio Debugging environment. 

    Given the (default) settings shown in the When Breakpoint Is Hit in Figure 1 and the code in Listing 1, the Output window in the IDE will contain the content shown in Figure 1.

    Listing 1: A simple ‘Jello Mold’ style demo with the Tracepoint as configured in Figure 1.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    namespace TracePointDemo
    {
      class Program
      {
        static void Main(string[] args)
        {
          Console.WriteLine("This is a test!");
          Console.ReadLine();

        }
      }
    }

    image
    Figure 2:  The Tracepoint writes the literal text and replaces the special keywords with their values, in this instance the function name and thread id is displayed in the Output window.

  • Using LINQ to DataTable and the ASPxTreeList Virtual Mode

         

    A customer posted a question to the forums, and I was asked to handle. Mehul Harry and the other guys have been pretty good to me on this front. They know I am busy with the book—Professional DevExpress ASP.NET Controls—and have been handling the.lion’s share of the forums work. However, the question was a LINQ question and I was happy to answer it. It’d probably be a waste to write a sample solution and share it with one person because as my associate Richard Morris put it: “Nice I just found a use for [“Converting SQL with Groups to XML Using LINQ and Functional Construction”] backing up data between XAF schema redesigns .... I love it when some seemingly random stuff precisely meets an unexpected requirement.” The web never sleeps, never runs out of space, the world is always awake somewhere and you never know what someone might need next.

    The question posed was basically how do I get the ASPxTreeList to work with the LinqServerModeDataSource. The answer is that the LinqServerModeDataSource isn’t presently designed to work with the ASPxTreeList. That’s ok though. The ASPxTreeList has a virtual mode. Virtual mode is basically where the tree looks fully loaded, but child nodes aren’t actually loaded until the parent is expanded, and then the child nodes a repopulated on an Ajax call. This means that even huge data sets can effectively be presented to the end user because the nature of trees is that the end user is generally drilling down into a branch of the tree.

    The key to all of this Ajax and virtual goodness is two event handlers: VirtualModeCreateChildren and VirtualModeNodeCreating. Simply implement VirtualModeCreateChildren and add child nodes based on the parent path and implement VirtualModeNodeCreating to fill in the details of each node. For example, if you have a column who’s field name is LastName then in VirtualModeNodeCreating you will want to set the LastName value for that node.

    An example—see Figure 1—based on the AdventureWorks database is provided below. The example uses the self-referentiating table HumanResources.Employee (which has an EmployeeID and a ManagerID and the ManagerID refers to the employee’s manager, a row in the same table). The root node or nodes are all employees that have no manager, logically such a person is the CEO or top guy. Underneath the CEO are people who report to the CEO and so on. Roughly, to construct the example follow these basic steps (you can always copy and paste the code to fill in the blanks):

    1. Create a Web site in Visual Studio
    2. Drop an ASPxTreeList in the <div> tag of the default.aspx page
    3. For the ASPxTreeList change SettingsBehavior.ProcessSelectionChangedOnServer to true
    4. Click on the Columns property and use the Columns editor (see Figure 2) to add a column to the ASPxTreeList
    5. Change the new column’s FieldName property to LastName
    6. Click OK to close the columns editor form
    7. Click on the ASPxTreeList’s Smart tags menu and select Edit Templates
    8. Select DataCell in the Display drop down and add two ASPxLabels to the DataCell template (see Figure 3)
    9. Using the Smart tags menu select Edit Bindings and define the binding statement for the Text property of each label—use Container.GetValue("EmployeeID") for the first label, and Container.GetValue("LastName") for the second label
    10. Click the ASPxTreeList’s Smart tags menu and select End Template Editing
    11. Define an event handler for each of the VirtualModeCreateChildren and VirtualModeNodeCreating events for the ASPxTreeList

    That’s it. You can now use the code in Listings 1 and 2 to fill in the blanks.  A brief explanation of the code behind follows listing 2.

    image
    Figure 1: The solution based on the AdventureWorks Employee table, LINQ and the ASPxTreeList using virtual mode.

    image
    Figure 2: Define a column for the ASPxTreeList and set the FieldName to ‘LastName’.

    image
    Figure 3: Add two ASPxLabel controls to the DataCell template.

    image
    Figure 4: Define the ASPxLabel’s binding statement using Container.GetValue(“name”) where “name” is the node value to assign to this control.

    Listing 1: The ASPX for the ASPxTreeList sample.

    <%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>

    <%@ Register assembly="DevExpress.Web.ASPxTreeList.v9.1, Version=9.1.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" namespace="DevExpress.Web.ASPxTreeList" tagprefix="dxwtl" %>
    <%@ Register assembly="DevExpress.Web.ASPxEditors.v9.1, Version=9.1.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" namespace="DevExpress.Web.ASPxEditors" tagprefix="dxe" %>

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
    </head>
    <body>
        <form id="form1" runat="server">
        <div>
        </div>
        <dxwtl:ASPxTreeList ID="ASPxTreeList1" runat="server"
          onvirtualmodecreatechildren="ASPxTreeList1_VirtualModeCreateChildren"
          onvirtualmodenodecreating="ASPxTreeList1_VirtualModeNodeCreating"
          AutoGenerateColumns="False">
          <SettingsBehavior ProcessSelectionChangedOnServer="True" />
          <Templates>
            <DataCell>
              <dxe:ASPxLabel ID="ASPxLabel1" runat="server"
      Text='<%# Container.GetValue("EmployeeID") %>'>
              </dxe:ASPxLabel>
              <dxe:ASPxLabel ID="ASPxLabel2" runat="server"
                Text='<%# Container.GetValue("LastName") %>'>
              </dxe:ASPxLabel>
            </DataCell>
          </Templates>
          <Columns>
            <dxwtl:TreeListTextColumn FieldName="LastName" VisibleIndex="0">
            </dxwtl:TreeListTextColumn>
          </Columns>
        </dxwtl:ASPxTreeList>
        </form>
    </body>
    </html>

    Listing 2: The code behind for the ASPxTreeList demo.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Data;
    using System.Data.SqlClient;

    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
        }

        public DataTable EmployeesTable
        {
          get
          {
            const string key = "EMPLOYEES_TABLE";
              if(Session[key] == null)
              Session[key] = GetTable();

            return (DataTable)Session[key];
          }
        }

        /// <summary>
        /// you could do this at the application level.
        /// </summary>
        public DataTable GetTable()
        {
          string connectionString =
            @"Data Source=WYOMING\SQLEXPRESS;" +
            "Initial Catalog=AdventureWorks;Integrated Security=True";

          string sql = "SELECT * FROM HumanResources.Employee E " +
              "INNER JOIN Person.Contact C ON E.ContactID = C.ContactID";

          using(SqlConnection connection = new SqlConnection(connectionString))
          {
            connection.Open();
            SqlCommand command =
              new SqlCommand(sql, connection);
            SqlDataAdapter adapter = new SqlDataAdapter(command);
            DataTable table = new DataTable();
            adapter.Fill(table);
            return table;
          }
        }

        protected void ASPxTreeList1_VirtualModeCreateChildren(object sender, DevExpress.Web.ASPxTreeList.TreeListVirtualModeCreateChildrenEventArgs e)
        {
          ASPxTreeList1.SettingsBehavior.AutoExpandAllNodes = false;
          // for the first one or root nodes
          int? key = null;
          e.Children = new List<DataRow>();

          if(e.NodeObject != null)
          {
            key = ((DataRow)e.NodeObject).Field<int?>("EmployeeID");
          }

          var data = from emp in EmployeesTable.AsEnumerable()
                     where emp.Field<int?>("ManagerID") == key
                     select emp;

          Array.ForEach<DataRow>(data.ToArray(), one=>e.Children.Add(one));

        }

        protected void ASPxTreeList1_VirtualModeNodeCreating(object sender, DevExpress.Web.ASPxTreeList.TreeListVirtualModeNodeCreatingEventArgs e)
        {
          DataRow row = (DataRow)e.NodeObject;
          e.NodeKeyValue = row.Field<int>("EmployeeID").ToString();
          e.IsLeaf = GetIsLeaf(row);
          e.SetNodeValue("EmployeeID", row.Field<int>("EmployeeID"));
          e.SetNodeValue("LastName", row.Field<string>("LastName"));
        }

        private bool GetIsLeaf(DataRow row)
        {
          return (from emp in EmployeesTable.AsEnumerable()
                  where emp.Field<int?>("ManagerID")
                    != row.Field<int>("EmployeeID")
                  select emp).Count() == 0;
        }
    }

    Once you know the basic trick—implement the two aforementioned event handlers—using ASPxTreeList in virtual mode is straight forward. In Listing 2 there is a helper method that returns the AdventureWorks Employee table using ADO.NET. How you actually get the data or whether you store it or query it each time is irrelevant. In the example, the Employee table is created using a lazy load and stored in Session. The important methods are VirtualModeCreateChildren and VirtualModeNodeCreating.

    In VirtualModeCreateChlidren a place to store data is create and assigned to TreeListVirtualModeCreateChildrenEventArgs.Children. Leaving this property unassigned means you can assign the kind of data structure you want. Next, the argument NodeObject property is checked. If its null then you are working with the root. In the listing, if its not null, the key is retrieved from the NodeObject. You know NodeObject is a DataRow because that’s what the code will be assigning to each node (see the end of the function). The key represents the manager and it is used in the where clause of the LINQ query to retrieve just this Employees subordinates—that is, the managed employees. Finally, the Array.ForEach adds each DataRow to the Children property. (Of course, that is a goofy statement, oops. List<T> has an AddRange method and that can be called passing the entire set of data. The reason I didn’t do that is because Children is defined as an IList. List<T> implements IList, but IList doesn’t require AddRange. Because Intellisense only showed Children.Add I ended with an Array.ForEach instead of an AddRange.)

    For every item added in VirtualModeCreateChildren VirtualModeNodeCreating will be called. Implement an event handler here to flesh out the node’s properties. In the event handler the NodeObejct is the DataRow for the node. Assign the key; it has to be unique. Since you are dealing with a primary key in the Employee table you can safely use the EmployeeID. Next, set IsLeaf. You can set IsLeaf to false to always show an expand and collapse icon. In Listing 2 another LINQ query is used to see if an employee is a manager—GetIsLeaf. Finally, set the values that you need displayed in the tree node. You can have as many as you like.

    That’s pretty much all there is to it. When you write this code a dozen times in a couple of weeks it will only take you a couple of minutes (after the practice). Of course, you can just defined the query with something like a SqlDataSource set the KeyFieldName and ParentFieldName for the ASPxTreeList and let her fly. Large data sets might be a problem with that approach. The key is knowing a couple of approaches to solving a problem and then use the one that causes you the least amount of pain.

  • Getting Client User and Special Folder Information with JavaScript

         

    You may on occasion want to query client information for your Web application using JavaScript. You can get this information by enabling unsigned ActiveX objects in IE and a couple of lines of code. The first short listing will return the client user information and the second short listing demonstrates how to return the path to special file folders for the user.

    var o = new ActiveXObject("WScript.Network");
    alert(o.UserName);

    var path = w.SpecialFolders("MyDocuments");
    alert(path);

    To enable unsigned ActiveX objects select  Tools|Internet Options and select the Security tab. Select the zone like Local intranet, click the Custom level button. Scroll down to the “Initialize and script ActiveX controls not marked as safe for scripting and change it to Enable or Prompt (see the Figure).

    image
    Figure 1: You can run ActiveX objects in your JavaScript for clients running IE.

    You may encounter different challenges in different zones. For example, running an application from the Internet may not work because of permissions set by network administrators that override all permissions. Unfortunately I am not aware of all possible combinations. Code like that above might be ideally suited for utility applications that run on a local PC only in the Intranet zone.

    Maybe some of our smart, savvy customers can respond and add to this blog post.

More from DevExpress
Live Chat
Have a pre-sales question?
Need assistance with your evaluation?
We are here to help.
Chat is one of the many ways you can contact members of the DevExpress Team. We are available Monday-Friday between 8:30am and 5:00pm Pacific Time.
If you need additional product information, require pre-sales assistance, or want help with your order, write to us at info@devexpress.com or call us at
+1 (818) 844-3383.