Click here to Skip to main content
15,868,141 members
Articles / Programming Languages / C#
Article

Using Windows Controls Remotely With .NET Remoting

Rate me:
Please Sign up or sign in to vote.
4.08/5 (6 votes)
3 Apr 2007CPOL2 min read 35.5K   967   21   3
The article describes how to share windows control functionality using .NET Remoting

Screenshot - RemoteWinControls.jpg

Introduction

In this article you will find a very interesting note about the way that you can share any kind of Windows control functionality from the server application to the client application.

Note

For simplicity purpose you will find no complex code in the source code.

Background

In the past if you shared a class with the .NET Remoting you would certainly know these notes:

  • You can't use a static member in the shared class.
  • You don't have access to shared class in the server application except when you share an instance with Marshal Method from RemotingServices class

Using the code

So, the code consists of three projects:

  • RemoteLib is a class library project and is the shared library.
  • It contains two classes:

    • RemotableClass is the shared class.
    • SharedResourcesHandler class contains shared controls in the static property form.

  • RemoteServer is a windows application project and is the hosting application for the RemoteLib library.
  • RemoteClient is a windows application project and is the client application for the RemoteLib library.

Shared Class Library

C#
/// SharedResourcesHandler Class ///

private static TextBox innerTextBox;
/// <summary>
/// Gets or sets the shared TextBox Control in the RemoteLib.
/// </summary>
public static TextBox InnerTextBox
{
    get { return innerTextBox; }
    set { innerTextBox = value; }
}

private static MonthCalendar innerMonthCalendar;
/// <summary>
/// Gets or sets the shared innerMonthCalendar Control in the RemoteLib.
/// </summary>
public static MonthCalendar InnerMonthCalendar
{
    get { return innerMonthCalendar; }
    set { innerMonthCalendar = value; }
}

Any kind of .NET controls could be used Instead of TextBox and MonthCalendar to be shared.

In the RemotableClass class you will use these controls to set properties.

Indeed the RemotableClass class is a wrapper class for publishing controls functionality to the clients.

C#
/// <summary>
/// Represents the method that will handle cross thread calls.
/// </summary>
/// <param name="text"></param>
private delegate void UIThreadHandler<T>(T param);

/// <summary>
/// Initializes a new instance of the RemotableClass
/// </summary>
public RemotableClass()
{

}
/// <summary>
/// Obtains a lifetime service object to control the lifetime policy for 
/// this instance.
/// </summary>
/// <returns>
/// An object of type System.Runtime.Remoting.Lifetime.ILease used to 
/// control the lifetime policy for this instance. This is the current 
/// lifetime service object for this instance if one exists; otherwise, a 
/// new lifetime service object initialized to the value of the 
/// System.Runtime.Remoting.Lifetime.LifetimeServices.LeaseManagerPollTime
/// property.
/// </returns>
public override object InitializeLifetimeService()
{
    ILease lease = (ILease)base.InitializeLifetimeService();
    if (lease.CurrentState == LeaseState.Initial)
    {
        lease.InitialLeaseTime = TimeSpan.FromMinutes(10);

    }
    return lease;
}


/// <summary>
///  Writes specified text to the TextBox Control.
/// </summary>
/// <param name="text"></param>
public void WriteText(string text)
{
    if (SharedResourcesHandler.InnerTextBox != null)
    {
        UIThreadHandler<string> uiThreadHandler = 
            new UIThreadHandler<string>(AsyncWriteText);
        
        if (SharedResourcesHandler.InnerTextBox.InvokeRequired)
            SharedResourcesHandler.InnerTextBox.BeginInvoke(uiThreadHandler,
               text);
        else
            SharedResourcesHandler.InnerTextBox.Text = text;
    }
}

/// <summary>
/// Writes specified text to the TextBox Control in the UI thread.
/// </summary>
/// <param name="text"></param>
private void AsyncWriteText(string text)
{
    SharedResourcesHandler.InnerTextBox.Text = text;
}


/// <summary>
///  Changes the MonthCalendar date to specified date.
/// </summary>
/// <param name="text"></param>
public void ChangeDate(DateTime date)
{
    if (SharedResourcesHandler.InnerMonthCalendar != null)
    {
        UIThreadHandler<DateTime> uiThreadHandler = 
            new UIThreadHandler<DateTime>(AsyncChangeDate);

        if (SharedResourcesHandler.InnerMonthCalendar.InvokeRequired)
            SharedResourcesHandler.InnerMonthCalendar.BeginInvoke(
            uiThreadHandler, date);
        else
            SharedResourcesHandler.InnerMonthCalendar.SetDate(date);
    }
}

/// <summary>
/// Changes the MonthCalendar date to specified date in the UI thread.
/// </summary>
/// <param name="text"></param>
private void AsyncChangeDate(DateTime date)
{
    SharedResourcesHandler.InnerMonthCalendar.SetDate(date);
}

Changing properties of shared controls must be a cross thread call, and done with a middle generic delegate named UIThreadHandler

Server Application

So where is the control when you are filling static members of the SharedResourcesHandler class?

The answer is one line per control in the server application like this:

C#
//Assigning Control from UI to static member of SharedResourcesHandler class
SharedResourcesHandler.InnerTextBox = this.txtRemote;
SharedResourcesHandler.InnerMonthCalendar = this.mcRemote;

Remaining server code is for Registering RemotableClass for enabling remote access

C#
TcpServerChannel channel = new TcpServerChannel(8080);
ChannelServices.RegisterChannel(channel, false);

RemotingConfiguration.ApplicationName = "RemotableClass";
RemotingConfiguration.RegisterWellKnownServiceType(typeof(
    RemoteLib.RemotableClass), "RemotableClass", 
    WellKnownObjectMode.SingleCall);

Also you can use the Remoting section in the server configuration instead of preceding code.

Client Application

In the client application the first step is getting remote object with this:

C#
TcpChannel channel = new TcpChannel();
ChannelServices.RegisterChannel(channel,false);
rClass = (RemotableClass)Activator.GetObject(typeof(RemotableClass), 
    "tcp://127.0.0.1:8080/RemotableClass");

I used localhost for testing purpose you can use any valid IP Addresses instead.

Also you can use configuration file to configure remoting enabled application.

Second step is calling shared object wrapper methods with events in the client application.

C#
/// <summary>
/// Calling WriteText method of RemotableClass
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void txtRemote_TextChanged(object sender, EventArgs e)
{
    rClass.WriteText(txtRemote.Text);
}

/// <summary>
/// Calling ChangeDate method of RemotableClass
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void mcRemote_DateChanged(object sender, DateRangeEventArgs e)
{
    rClass.ChangeDate(mcRemote.SelectionStart);
} 

This is a test application, in your real application you must use this trick object oriented.

License

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


Written By
Program Manager System Group
Iran (Islamic Republic of) Iran (Islamic Republic of)
Hossein Ghahvei Araghi
Birth date: 1978
Birth place: Iran
Academic Credentials : BS(Tehran University)
Microsoft Credentials : MCP, MCAD, MCTS 2.0, MCTS 3.5, MCPD 2.0, MCPD 3.5

Comments and Discussions

 
GeneralInteresting and Innovative Pin
IgDev4-May-07 4:50
IgDev4-May-07 4:50 

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

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