How Do I Display a List With Control IDs in a Control's Property?

When you're building your own Server Controls you may have the need to hook up one control to another. This is a common practice with the ASP.NET Validator controls, for example. As soon as you drop a validator control on your page, the ControlToValidate drop-down displays a list with controls that can be validated. Adding this behavior to your own server controls is not as difficult as you might think.

To implement this behavior, you'll need to create your own TypeConverter class. Andy Smith already has done all the hard work by creating a class called ServerControlConverter that derives from StringConverter. You can check out his blog about this class to see how it works. The class has a method called IncludeControl that can be overriden by a class deriving from ServerControlConverter to limit the list of control IDs returned to those of a specific type.

Let's assume your Web Control Library project in Visual Studio .NET contains two controls: ControlA and ControlB. ControlB has a property called ControlToValidate (although you can choose another name that makes more sense) which accepts the ID of another control as a string. To make it easier for your control users to bind a control to this property in a visual designer like Visual Studio .NET or the Web Matrix, the property grid for ControlB should display a drop-down with the IDs of all controls of type ControlA that are available on the current page:

The Property Grid for a control that allows you to select an instance of ControlB
Figure 1: The Properies Dialog for the Control

Let's look at how you can accomplish this:

  1. In the Web Control Library project with your two server controls (ControlA and ControlB in this example), add a new class file and call it ServerControlConverter.cs. Copy and paste the code for the ServerControlConverter class from Andy's web blog to that file.
  2. Add a second class file and call it ControlAConverter.cs. The ControlAConverter class will inherit from the ServerControlConverter and override the IncludeControl method, so it only returns true when the control is of type ControlA. Add the following code to the class file:
    using System;
    using System.Web.UI;
    namespace MyControls
    {
      public class ControlAConverter: ServerControlConverter
      {
        protected override Boolean IncludeControl(Control serverControl) 
        {
          if (serverControl is ControlA)
          {
            return true;
          }
          else
          {
            return false;
          }
        }
      }
    }
    


    Make sure that the original ServerControlConverter and ControlAConverter class are both in the same namespace, or change the code to match your namespace conventions.

  3. The next step is to hook up the property of your ControlB control to this type converter. You can do that by adding a TypeConverterAttribute attribute to the property definition. The TypeConverterAttribute is usually abbreviated to just TypeConverter.
    In the ControlB class, right above the property definition, add the following code:
    string controlToValidate = "";
    
    [
      TypeConverter(typeof(ControlAConverter))
    ]
    public string ControlToValidate
    {
      get
      {
        return controlToValidate;
      }
      set
      {
        controlToValidate = value;
      }
    }
  4. Finally, save all your pages, and compile the control. In your ASP page, add your controls to the toolbox and drag a couple of instances of ControlA on an .ASPX page. Next, drag an instance of ControlB on the page. Make sure the instance of ControlB is selected on the designer surface, and then select the ControlToValidate property in the property grid. Instead of a regular text field, you'll see a drop-down that lists the IDs of all controls of type ControlA, just like the screen shot earlier in this article.

That's all there is to it. From this point on, the private field controlToValidate can contain the ID of another control. To access that control at run-time, use code similar to this:

if (controlToValidate.Length > 0)
{
  if (this.Page.FindControl(controlToValidate) != null)
  {
    ControlA myControlA = (ControlA)this.Page.FindControl(controlToValidate);
    // Do whatever you need to do with the instance of myControlA, like
    // accessing its properties:
    string testString = myControlA.AStringProperty;
  }
}

If you don't want the end users of your control to manually add the ID of a control, but limit them to those presented in the list instead, you'll need to override the method GetStandardValuesExclusive. That method in the base class ServerControlConverter returns false by default, allowing items to be entered directly in the property grid. Add the following code to your ControlAConverter class to disallow manual items:

public override bool GetStandardValuesExclusive(ITypeDescriptorContext context) 
{
  return true;
}
With this code, the list with control IDs exclusively lists the IDs of the controls it finds on the page and that are of type ControlA, preventing your users from adding unknown or illegal IDs directly.

Download Files

Source Code for this Article

Where to Next?

Wonder where to go next? You can read existing comments below or you can post a comment yourself on this article .


Consider making a donation
Please consider making a donation using PayPal. Your donation helps me to pay the bills so I can keep running Imar.Spaanjaars.Com, providing fresh content as often as possible.



Feedback by Other Visitors of Imar.Spaanjaars.Com

On Wednesday, November 30, 2005 4:00:33 AM Anderman said:
Thanks!!! I've been looking for this for a while now. This is perfect.

Talk Back! Comment on Imar.Spaanjaars.Com

I am interested in what you have to say about this article. Feel free to post any comments, remarks or questions you may have about this article. The Talk Back feature is not meant for technical questions that are not directly related to this article. So, a post like "Hey, can you tell me how I can upload files to a MySQL database in PHP?" is likely to be removed. Also spam and unrealistic job offers will be deleted immediately.

When you post a comment, you have to provide your name and the comment. Your e-mail address is optional and you only need to provide it if you want me to contact you. It will not be displayed along with your comment. I got sick and tired of the comment spam I was receiving, so I have protected this page with a simple calculation exercise. This means that if you want to leave a comment, you'll need to complete the calculation before you hit the Post Comment button.

If you want to object to a comment made by another visitor, be sure to contact me and I'll look into it ASAP. Don't forget to mention the page link, or the QuickDocId of the document.

For more information about the Talk Back feature, check out this news item.