Click here to Skip to main content
Click here to Skip to main content

Signal Strength Control in C#

, 8 Jan 2010 CPOL
Rate this:
Please Sign up or sign in to vote.
A signal strength control similar to the ones on cell phones

Introduction

This is a relatively simple control that illustrates some of the techniques used in developing custom controls. We will look at the way we hide properties that we don't want exposed through the designer, correctly listing our custom properties, and some other pointers.

Background

Custom controls and design-time support are a little daunting, the MSDN documentation is difficult to wade through and unless we are shown how to do something, it isn't always apparent. I've been developing custom controls for a few years now and I'm still learning the intricacies of custom control development and rich design-time support. Hopefully this article will shed some light on the dark world of control development.

Hiding Properties

Before I really get into the meat of the SignalStrengthMeter, I want to delve into some control development subjects. The first of which is hiding properties at design time.

When you create a new custom control in Visual Studio, you inherit from the UserControl class most of the time. You can elect to inherit from just about any control, even things like Buttons, Panels, radio buttons, etc. It's best to pick a control that most closely represents the control that you want to develop. The problem is that whatever control you decide to inherit from, you are bound to have a bunch of properties in the window that don't do anything, or make no sense to what you are developing.

That's where property hiding comes in. Every property has a bunch of design time metadata associated with it, you just need to change the metadata so it doesn't show up in the properties window. The only way (that I've found at least) is to create a new "hiding" property and assign the proper metadata to it, like:

[Browsable(false), DesignerSerializationVisibility
	(DesignerSerializationVisibility.Hidden), 
EditorBrowsable(EditorBrowsableState.Never)]
public new Image BackgroundImage
{
    get { return base.BackgroundImage; }
    set { base.BackgroundImage = value; }
} 

There are a couple interesting notes, the first is that the property has the keyword "new" in it before the type. This identifies to the compiler that you intend to "hide" the base type's implementation of that property (go ahead and remove it and try to compile, look at the error). Next are the Browsable and DesignerSerializationVisibility. Setting the Browsable attribute with the initializer false tells the Visual Studio designer that you don't want to show the property at design time. Setting the DesignerSerializationVisibility to "Hidden" tells the designer that you don't want to serialize (save) the settings of this property at design time.

Unfortunately this doesn't hide the property in code, it's still there bright as day. Even setting the access level to private or protected won't remove the member from code.

Describing Your Properties

This is one of the biggest problems you see with the homebrew controls you find in places like CodeProject, nobody takes the time to categorize or describe the controls so that you have a rich design time experience. Think of the poor developer that has to use your code!

There are 3 important settings to use when describing your data:

  • Browsable(true)
  • Category("Category Name")
  • Description("Description")

Obviously there are a lot more, but those are the basics. You might also want to look into using the DefaultValue property, which you can use to identify what the default is (so the value isn't Bolded in the properties window).

Here is an example of applying the three main attributes (and 2 others I'll describe below):

[Browsable(true), EditorBrowsable( EditorBrowsableState.Always), 
	Bindable( BindableSupport.Yes), 
Category("Appearance"), Description("Number of bars in the signal monitor")]
public int NumberOfBars
{
    get { return numberOfBars; }
    set { numberOfBars = value; this.Invalidate(); }
}   

You can see that I applied the Browsable attribute so that it shows up in the properties window, the Category attribute to place the property in the Appearance category in the properties window, and Description so that when the user has the property selected, the description box at the bottom of the properties window shows a friendly description of the property.

I also used two other attributes I won't get into too much detail about, but you can set certain properties of your control to be "Advanced" properties, I always set this to always show, even though I can't find the place to hide advanced properties in Visual Studio. The second one describes the property as "bindable", meaning I'm allowing the application to bind to it for data driven applications (in my case I use them for skinning, but not in this project).

One last note about the Metadata; there is a metadata attribute called DisplayName, where you can set the name of the property to anything you want, so you can turn "NoSignalThreshold" into "No Signal Threshold". I would AVOID using this attribute. Why? Well if some developer down the line wants to extend your control, or base a new one off of your control, it makes it very difficult to hide the property if you have to search through Intellisense for it, when the actual property name doesn't match what is in the property window.

Custom Control Regions

I always hate the fact that setting a background as "transparent" really doesn't mean transparent, it just means it'll suck the background color off of its parent control (yes, a form is a control), and use that. I've written into this control the ability to set the control as truly transparent, by using a custom control region. You can take a look through the CalculateRegion() function to see how I've implemented it, but basically you just need to draw a GraphicsPath with the areas that you want, and leave everything else out.

This may have some performance implications since Windows now has to do some fancy clipping with complicated regions, but I think the visual payoff is worth it. The only problem is that if you set this control over another control (like a button), the user can click in between the regions and affect the control underneath it.

Using the Code

I'm not going to get into the implementation details heavily because there really isn't anything revolutionary about the code. It just draws a number of bars, calculating if they are filled or not, what the fill style is (Solid or Gradient), and what the color should be depending on the "quality" of the signal. Using the control is self explanatory, just drop the control on your form, set the MinValue and MaxValue properties, then set the value property.

You can set the orientation to be from right to left, left to right, top to bottom, and bottom to top. One thing I neglected to do was to make them top, bottom, left, or right justified, this is a possible future enhancement.

Points of Interest

UI development is a lot more art than skill, unfortunately I'm not very artful, there could be a lot of improvements to the look and feel of this control, go nuts!

History

  • Version 1.0 - Initial release
  • Version 1.1 - Bug fix: BottomToTop layout style didn't calculate region if set to Transparent

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Ron Beyer
President 6D Systems LLC
United States United States
I studied Software Engineering at Milwaukee School of Engineering for 2 years before switching to Management of Information Systems for a more business oriented approach. I've been developing software since the age of 14, and have waded through languages such as QBasic, TrueBasic, C, C++, Java, VB6, VB.NET, C#, etc. I've been developing professionally since 2002 in .NET.

Comments and Discussions

 
GeneralAnother way to hide parent properties PinmemberAtanas Palavrov11-Jan-10 21:55 
GeneralGreat Work! PinmemberEckel Chung9-Jan-10 4:11 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.141216.1 | Last Updated 8 Jan 2010
Article Copyright 2010 by Ron Beyer
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid