ib11
ib11

Reputation: 2568

Visual C# returning value from an event handler

I have a form that has a button to get a method executed in another class.

Code on the form:

public delegate void CustomPreviewCreate();
public static event CustomPreviewCreate CustomPreviewCreate_Do;

private void CreatePreview()
{
    if (CustomPreviewCreate_Do !=null)
    {
        CustomPreviewCreate_Do();
    }
}

This event then gets handled in another class. What I would like to achieve is that I can feed back to the form some form of return value if the method correctly executed.

What I tried so far does not get me the result.

Here is the code:

public void Initialize()
{
    SubAsstViewPartControl.CustomPreviewCreate_Do += SubAsstViewPartControl_CustomPreviewCreate_Do;
    // this gives me a the compiler error that the return type is wrong
}

private bool SubAsstViewPartControl_CustomPreviewCreate_Do()
{
    // do stuff
    return false;
}

Is there any direct way to return value from an event handler or I need to use a separate static field to store the event result in?

Update:

Per @Jon's comment, which seemed the simplest to me, I added an answer below demonstrating the simplest approach.

Upvotes: 0

Views: 7430

Answers (2)

ib11
ib11

Reputation: 2568

Per Jon Skeet's comment, which seemed the simplest to me, the simplest approach seems to be as follows:

public delegate bool CustomPreviewCreate(); // here we declare a return type
public static event CustomPreviewCreate CustomPreviewCreate_Do;

private void CreatePreview()
{
    if (CustomPreviewCreate_Do !=null)
    {
        bool returnval = CustomPreviewCreate_Do();
    }
}

And then:

// the method is declared to return the same type
bool SubAsstViewPartControl_CustomPreviewCreate_Do()  
{
    // do stuff
    return true;  // return the value of the type declared
}

Upvotes: 0

Kai van Lopik
Kai van Lopik

Reputation: 246

The common approach is to encapsulate your value in the type of EventArgs your event expects. For example, the Framework's CancelEventArgs contains a settable bool Cancel property, allowing each CancelEventHandler to assign a value. The sender can then read the property after the event has been invoked. You could also use a container-like EventArgs class if you want to collect separate values from individual event handlers. For example:

using System;
using System.Collections.Generic;

namespace ConsoleApplication1
{
  public class SingleValueEventArgs : EventArgs
  {
    public int Value { get; set; }
  }

  public class MultiValueEventArgs : EventArgs
  {
    private List<int> _values = new List<int>(); // Private to prevent handlers from messing with each others' values

    public IEnumerable<int> Values
    {
      get { return _values; }
    }

    public void AddValue(int value) { _values.Add(value); }
  }

  public class Exposer
  {
    public event EventHandler<SingleValueEventArgs> WantSingleValue;
    public event EventHandler<MultiValueEventArgs> WantMultipleValues;

    public void Run()
    {
      if (WantSingleValue != null)
      {
        var args = new SingleValueEventArgs();
        WantSingleValue(this, args);
        Console.WriteLine("Last handler produced " + args.Value.ToString());
      }

      if (WantMultipleValues != null)
      {
        var args = new MultiValueEventArgs();
        WantMultipleValues(this, args);
        foreach (var value in args.Values)
        {
          Console.WriteLine("A handler produced " + value.ToString());
        }
      }
    }
  }

  public class Handler
  {
    private int _value;

    public Handler(Exposer exposer, int value)
    {
      _value = value;
      exposer.WantSingleValue += exposer_WantSingleValue;
      exposer.WantMultipleValues += exposer_WantMultipleValues;
    }

    void exposer_WantSingleValue(object sender, SingleValueEventArgs e)
    {
      Console.WriteLine("Handler assigning " + _value.ToString());
      e.Value = _value;
    }

    void exposer_WantMultipleValues(object sender, MultiValueEventArgs e)
    {
      Console.WriteLine("Handler adding " + _value.ToString());
      e.AddValue(_value);
    }
  }

  class Program
  {
    static void Main(string[] args)
    {
      var exposer = new Exposer();

      for (var i = 0; i < 5; i++)
      {
        new Handler(exposer, i);
      }

      exposer.Run();
    }
  }
}

Upvotes: 2

Related Questions