Component
: an object that is reusable and can interact
with other objects.
.NET Framework
component:
“additionally
provides features such as control over external resources and design-time
support.” [Visual
Studio Help].
As a good software
engineer, you want to decompose your applications into small functional units
with well-defined interfaces to each other.
Hopefully these modules can be re-used in various applications and can
be more easily maintained as components than as parts of a huge
application.
In the Windows API and
in MFC, components are implemented as DLLs (dynamic link libraries). In FCL, that is also true: when we choose as the project type Class
Library, and build the project, a DLL file is produced. But the FCL library
and Visual Studio provide some support to make the creation and use of class
libraries easy. In MFC, there were quite
a few technical difficulties if you wanted to include a class in a DLL and export
its methods. (“Export” here means “make
available for other components to use”.)
In
the .NET Framework, a component is a class that implements the System.ComponentModel.IComponent interface or that
derives directly or indirectly from a class that implements IComponent.
That
is mysterious since we don’t know what the interface IComponent
is. But we don’t need to know
that. We only need to know that there
are two important FCL classes that implement that interface: Component and Control. Corresponding to these choices, there are
two “project types” available in Visual Studio:
·
Windows Control Library: for a
control that has a user interface; you will use the Form Editor to design this
interface.
·
Class Library: exposes functionality by
offering classes and methods only, without needing a designable user
interface.
Remotable
components that encapsulate system resources, that are large, or that exist as
single instances should be marshaled by reference. The base class for
components that are marshaled by reference is System.ComponentModel.Component.
This base class implements IComponent and
derives from MarshalByRefObject. Many
components in the .NET Framework class library derive from Component,
including System.Windows.Forms.Control (the
base class for Windows Forms controls), System.Web.Services.WebService
(the base class for XML Web services created using ASP.NET), and System.Timers.Timer (a class that generates
recurring events).
Remotable
components that simply hold state should be marshaled by value. The base class
for components that are marshaled by value is System.ComponentModel.MarshalByValueComponent.
This base class implements IComponent and
derives from Object. Only a few components in the .NET Framework
class library derive from MarshalByValueComponent.
All such components are in the System.Data
namespace (DataColumn, DataSet,
DataTable, DataView,
and DataViewManager).
Example. Let’s say that we possess code to display
mathematical formulas presented as a String.
We wish we had a Formula control that we could drag and drop onto
a Windows form, with a property that would hold the string form of the formula,
for example (x^3 + 1)/(x^2-1), which
would be displayed as

We will show how this
is done, but skipping the complicated
display code, we’ll just have the control call DrawString
to display the string form. This will
still demonstrate how to create and use a custom control. Here are the steps to follow:
1. Create a new project, choosing Windows Control
Library. Call your project, for example, ControlDemo.
You’ll see a form on the Form Designer, smaller than you see for an
application.
2. Add a member variable String formulaString; to do that, just type in the declaration in
the .cs file.
3. In the Form Designer, right-click your form and add a
handler for the Paint event. In
your Paint method,
create a Font and SolidBrush and call DrawString to display formulaString.
4. Now create a second project, choosing Windows
Application. Be sure to select the
radio button to add to solution,
rather than create a new solution.
This will be the host application.
Observe in Solution Explorer that you have a reference to ControlDemo.
5. The
documentation alleges, and in Visual Studio 2003 it was true, that with the
Form Designer open on your new project, you should see a tab at the left
labeled My User Controls, and under that tab you should see your new
control listed. Here is a screen shot
from Visual Studio 2003, but I couldn’t
get this to happen in Visual Studio 2005!

6. Eventually, I figured out how to get my
control to appear in the toolbox:
Right-click the Toolbox in some blank place,
and choose Choose Items from the context menu. That will bring up this dialog:

Click “Browse” and
browse to the folder of your control project, then to its
Bin/Debug
subfolder, and select the .dll file containing the
executable code. (Of course, if the
control is already debugged and you’re just using it, then you would use the
release version.) Now you should see userControl1 (or whatever you named your
control) in the
Toolbox, and you can drag one onto your Form1.
6. In the constructor of your host project, add this line after
the call to InitializeComponents:
userControl11.stringFormula =
"(x^3+1)/(x^2-1)";
Incidentally, observe
that Visual Studio wrote this code for you:
private void InitializeComponent()
{ this.userControl11
= new ControlDemo.UserControl1();
this.SuspendLayout();
}
It seems to work fine
to add the initialization of stringFormula in InitializeComponent, but I’m wary of editing automatically
generated code, as sometimes what you write there disappears upon a later use
of the design editor, so I think it is better to put your code in the
constructor after the call to InitializeComponent.
7. Right-click your host project in Solution
Explorer and choose Set as Active Project. Then run it.
You should see the result

If you don’t set the
host project as active project first, you won’t be able to run, because a
component can’t be the startup project.
Final Remarks
To make this a useful
component, of course, we would have to write or import the code for the
two-dimensional display of the formula. In practice that is a problem, because the
code is in “unmanaged” C, not in “managed C++” or in C#. This problem is solvable, but not pretty.
Also, it would be nice if this component would
work on a web page. I believe it would
work on a web page if the web server is Microsoft’s server (IIS), and if the
user’s browser is Internet Explorer, but it won’t work otherwise. That makes it useless for web pages, in my
opinion. But it still might be useful
in building applications.
Although in theory you
could “remote” this component, I wasn’t able to accomplish it. Add Web Reference is only useful for
using a web service.