0

I have a class and a form. the class is intended to do some processes when event is raised and return back the values to the form to display only. I kind of have problem passing values back to form. For instance, I have this code in class print:

  public class PrintClass : Form1
{

    public void printEventHandler(object sender, EventArgs e)
    {

        string text = "Process Completed";
        append_Tbox(text);

    }

}

and the method in form1 to display the text:

  public void append_Tbox(string s)
    {

        TboxPrint.AppendText(s);
    }

However, nothing is displayed. I believe there is something wrong, but I can't figure it out. What is the fastest way to pass values from the class to form?

7
  • From the code you have provided it looks like the append_Tbox fucntion is in the same class. Am I correct Commented Feb 25, 2013 at 5:24
  • @Vikram, the class PrintClass inherits the form1, that is why i can directly call the method. Commented Feb 25, 2013 at 5:26
  • @Liban- you can't access the TxtBox outsude the class, beause the Both Controls are Private, see the Designer.cs Commented Feb 25, 2013 at 5:37
  • @AkshayJoy, i m not accessing the txbox outside the class, i m accessing the method inside the form, that display to txtBox. Commented Feb 25, 2013 at 6:31
  • 1
    You need you delegate... I think if you use delegate you can achieve this. Commented Feb 25, 2013 at 6:34

3 Answers 3

1

First off, your processing class shouldn't extend Form1. This is giving you the illusion that you can access the methods of your existing form, but it's not doing what you think it is. You're creating an entirely new form when you do this, and just not showing it. That form has it's own set of all instance fields, so you're not accessing the controls of your main form. Even if this would work (and it won't) it's not a well designed solution.

The proper way to do this is actually much easier. You just need to have your other class return a value from it's method:

public class PrintClass
{
    public string DoWork()
    {
        Thread.Sleep(2000);//placeholder for real work.
        return "Process Completed";
    }
}

Now your main form can just call that method and append the return value to a textbox.

Once you do this you'll have an entirely separate issue. If you do the work in the UI thread you'll be blocking that UI thread while the work takes place, preventing the form from being repainted, or any other events from being handled. You need to do the work in a background thread and then marshal back to the UI thread to update the UI with the results. There are a number of ways of doing this, but if you have C# 5.0 using await is by far the easiest:

public class Form1 : Form
{
    private void SomeEventHandler(object sender, EventArgs args)
    {
        string result = await Task.Run(()=>new PrintClass().DoWork());
        TboxPrint.AppendText(result);
    }
}

If you need a C# 4.0 solution you can use ContinueWith, which is more or less what the above will be translated to, but it's not quite as clean of syntax.

public class Form1 : Form
{
    private void SomeEventHandler(object sender, EventArgs args)
    {
        Task.Factory.StartNew(()=>new PrintClass().DoWork())
            .ContinueWith(t => TboxPrint.AppendText(t.Result)
                , CancellationToken.None
                , TaskContinuationOptions.None
                , TaskScheduler.FromCurrentSynchronizationContext());
    }
}
Sign up to request clarification or add additional context in comments.

6 Comments

in SomeEventHandler method, which event it is handling? by the way, in think there is no await in c#4.0
@Liban Whatever event you want this work to be done it; it doesn't really matter much. There is only one event you're dealing with, from the sound of it. You are correct, there is no await in C# 4.0, which is why I said you can do this if you're using C# 5.0.
is there any alternative for Task.Run? because it gives an error: 'System.Threading.Tasks.Task' does not contain a definition for 'Run'. maybe it doesnt exist c#4.0. i tried to look for other alternatives but i couldnt.
@Liban Right, minor change; it's Factory.StartNew. Copy-paste error.
yes, the Factory.StartNew worked. just needed to add the btnclick to 'SomeEventHandler'. thanks.
|
0

I have create delegate in Main Form

 public delegate void LoginDelegate(string s);

 public partial class AirLineReservationMDI : Form
    {
        LoginDelegate loginAirLineDelegate;

    }

loginAirLineDelegate = new LoginDelegate(DisableToolStripMenuItems);


 public void DisableToolStripMenuItems(string s)
        {
           this.viewToolStripMenuItem.Visible = true;
            this.bookingToolStripMenuItem.Visible = true;
            this.existingUserToolStripMenuItem.Visible = false;
            this.newUserToolStripMenuItem.Visible = false;
            this.toolStripStatusUserID.Text = "USerID :- "+s;             
           this.LoginUserId = s;
        }

in Another Class, (I have passed delagete object to this class ) I fired the Delegate

  logDelegate(textBoxUserName.Text);

4 Comments

That won't work, as the delegate will still be acting on an incorrect instance of the form.
Servy- I have used the Delagete to perform this activities. he needs to set TxtValue form another class, better and easy option is Deleagte, we are using delegate to achieve this functionalities.
You have not addressed my comment at all; you've just stated several unrelated facts that don't really mean anything. Using a delegate, in this case, is no different than just calling the method directly, which isn't working for him. This answer is not helpful and doesn't address the underlying problems the OP is having.
@Servy - he accepted my answer. delegate solved problem. atually things to be done, no matter how.? and where?. just read about the deleagates.
0

I used Action<T> delegate to solve the problem. here is the code and it works fine.

 class PrintClass 
{
    public Action<string> DisplayDelegate;


    public void printEventHandler(object sender, EventArgs e)
    {
        string text = "Event Handled, and text value is passed";

        var copy = DisplayDelegate;

        if (copy != null)
        {
           copy(text);
        }
    }

}

and in `Form1.cs' :

 private void Form1_Load(object sender, EventArgs e)
    {
        PrintClass p = new PrintClass();
        BtnPrint.Click += p.printEventHandler;

        //subscrite the displayevent method to action delegate
        p.DisplayDelegate += DisplayEvent;

    }


    public void DisplayEvent(string s)
    {

        Invoke(new Action(() => TboxPrint.AppendText(s)));
    }

so the text 'Event Handled, and text value is passed' is displayed on the textbox.

I m not sure if it is the efficient way. Thanks guys.

2 Comments

Does your actual print event handler take long to run? This one isn't really doing anything, but if the true event will spend a significant amount of time doing processing then that work will be blocking the UI thread, which is a problem. Also, if you do use this, you should use an event, rather than a raw delegate. Simply use public event Action<string> DisplayDelegate; instead within PrintClass. You should also probably call it something more like PrintCompleted rather than DisplayDelegate, as that more properly indicates what it is.
you are right. it block the UI thread. thanks for the clarification. it really helped me to get the point.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.