2

Im making a program what connects to multiple 3th party systems. The connect with different formats so i created multiple classes to deal with them. I have now three 4 classes.

  • The MainForm is the first class. This is the basic windows form class with the user interface.

  • SDKCommunication is the second class.

  • VMS (this class handles the events given of by the 2th party system and activates methods on SDK COmmunication)

  • Events

Events Class

public class Events
{
    public event EventHandler LoginStateChanged;
    private bool loginstate;

    public bool LogInState
    {
        get { return this.loginstate; }
        set
        {
            this.loginstate = value;
            if (this.LoginStateChanged != null)
                this.LoginStateChanged(this, new EventArgs());
        }
    }
}

part of SDKCommunicatie class

Events events = new Events();        
public void onLogon(string username, string directory, string system)
{
  events.LogInState = false;
}

MainForm Class

SDKCommunicatie sdkcommunicatie = new SDKCommunicatie();
Events events = new Events();
public MainForm()
{
    InitializeComponent();
    events.LoginStateChanged += new EventHandler(events_LoginStateChanged);
}
void events_LoginStateChanged(object sender, EventArgs e)
{
    log.Info("EventFired loginstateChanged");
}

When the LogInState Changes in the SDKCommunicatie class. There needs to be an event fired in the MainForm class. But sadly that doesn't work. But when I change the loginstate in the mainform(with a buttonclick)(see code below) the event is fired. But that is not the intention i would like to have.

private void button1_Click(object sender, EventArgs e)
{
      events.LogInState = true;
}

If my question isn't clear enough, please let me know.

VMS class Added as reply to @Astef

class VMS        {
        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(MainForm));
        GxUIProxyVB m_UIProxy = new GxUIProxyVB();

        public string username2;
        public string directory2;
        public string Status;

        public void initOmni()
        {

            m_UIProxy.CreateInstance();
            m_UIProxy.OnLogon += new _IGxUIProxyVBEvents_OnLogonEventHandler(m_UIProxy_OnLogon);
            m_UIProxy.OnLogoff += new _IGxUIProxyVBEvents_OnLogoffEventHandler(m_UIProxy_OnLogoff);
            m_UIProxy.OnError += new _IGxUIProxyVBEvents_OnErrorEventHandler(m_UIProxy_OnError);
            m_UIProxy.OnAlarmStatusEx2 += new _IGxUIProxyVBEvents_OnAlarmStatusEx2EventHandler(m_UIProxy_OnAlarmStatusEx2);

        }



        public void login(string username, string password, string directory)
        {
            username2 = username;
            directory2 = directory;
            initOmni();
            m_UIProxy.LogOn(directory, username, password,false);

        }
        public void logOff()
        {
            m_UIProxy.LogOff();
        }

        void m_UIProxy_OnLogon()
        {
            SDKCommunicatie sdkcommunicatie = new SDKCommunicatie();
            sdkcommunicatie.onLogon(username2, directory2, "Genetec Omnicast");
        }

I have fixed this with deleting the following:

SDKCommunicatie sdkcommunicatie = new SDKCommunicatie();

And adding the following in the base of VMS:

SDKCommunicatie sdkcommunicatie;

But now i got a new error in the mainform when i tried to call a class in SDKCommunicatie

connectedStatus = sdkcommunicatie.connectedStatus();

I got the following error:

NullReferenceException was unhandled

2
  • 1. Remote collaborate debugging of your code is not the purpose of this place. May be you'd better use codereview.stackexchange.com 2. If you want to program, you need to learn how to investigate exceptions by yourself. Usually there's a lot of them and that is normal. 3. Your project design is horrible, learn about SOLID principles (may be in future) Commented May 7, 2013 at 8:48
  • Im sorry if this was the wrong way to do it. I'm fearly new to programming in C# and new to stackoverflow. In learning C# i used a lot of tutorials and also this site but never asked questions on this website. Commented May 7, 2013 at 8:58

4 Answers 4

2

You are not using the same instance of the Events class, and that's why on button click you catch LoginStateChanged. You should inject the same instance of Events class to SDKCommunicatie class, then you'll be able to listen to event changes.

Edit: Jeremy Todd and I were both writing at the same time.

Sign up to request clarification or add additional context in comments.

Comments

2

Events in your SDKCommunicatie are not fired because you've created an individual instance of class Events for it. That is not the instance you have placed on the MainForm.

Inject the right instance (pass a reference) to SDKCommunicatie from MainForm through constructor, property or somehow else. For example:

MainForm:

SDKCommunicatie sdkcommunicatie;
Events events = new Events();
public MainForm()
{
    InitializeComponent();
    events.LoginStateChanged += new EventHandler(events_LoginStateChanged);
    sdkcommunicatie = new SDKCommunicatie(events);
}
void events_LoginStateChanged(object sender, EventArgs e)
{
    log.Info("EventFired loginstateChanged");
}

SDKCommunicatie:

Events events;
public SDKCommunicatie(Envents eventsInstance)
{
    events = eventsInstance;
}
public void onLogon(string username, string directory, string system)
{
  events.LogInState = false;
}

3 Comments

Thank you for your example code. This looks like it should fix it. But now i get an error when my third class tries to call a method in SDKCommunicatie. SDKCommunicatie sdkcommunicatie = new SDKCommunicatie(); sdkcommunicatie.onLogon(username2, directory2, "Genetec Omnicast"); I get the error that its inaccessible due to its protection level. Could you please provide me with an example how to fix this.
@Gulpener Be sure that SDKCommunicatie constructor is public. If it not helps, you need to show your code
Thank you for your help. I got a new error. I added the changed code in the original post.
1

Your SDKCommunication class and your MainForm class each have their own separate instance of Events, so any events you trigger from one won't be visible from the other -- they're being raised on an entirely different object.

What you need is a single instance of the Events class that both SDKCommunication and MainForm can share -- that way they'll both be seeing the same thing. There are several different approaches you could take for this. Depending on what it needs to do, one very simple possibility might be to make Events a static class, and then the events would be visible everywhere without needing to create any instances.

Comments

0

I have solved the riddle. When i need a method is a class i can call the method directly like this:

public class MainForm : Form
{
   SDKCommunication sdkcommunication = new SDKCommunication();

   public MainForm()
   { 

   }

   private void Button1_Click(oject sender, EventArgs e)
   {
      sdkcommunication.method("Test")
   }
}

This is pretty straightforward. Look here the receiverclass:

public class SDKCommunication
{
    method(string word)
    {
       //do something with word
    }
}

The biggest problem is calling the class with the form(the original class). I have solved this with a eventhandler.

class CustomEventHandler1 : EventArgs
{
   public CustomEventHandler1(string u, string d)
   {
      msgu = u;
      msgd = d;
   }
   private string msgu;
   private string msgd;
   public string Username
   {
     get { return msgu; }
   }
   public string Directory
   { 
     get { return msgd; }
   }
}

Then the SDKCOmmunication class should look like this:

class SDKCommunication
{
   public event EventHandler<CustomEventHandler1> RaiseCustomEventHandler1;

   protected virtual void OnRaiseCustomEventHandler1(CustomEventHandler1 e)
   {
      EventHandler<CustomEventHandler1> handler = RaiseCustomEventHandler1;
      if (handler != null)
      {
         handler(this,e);
      }
   }

   //Custom Method that is called somewhere
   internal void custommethod()
   {
      OnRaiseCustomEventHandler1(new CustomEventHandler1("johnsmith", "localhost");
   }
}

Then in the mainform class:

public class MainForm : Form
{
   public MainForm()
   {
      sdkcommunication.RaiseCustomEventHandler1 += new  EventHandler<CustomEventHandler1>(sdkcommunication_RaiseCustomEventHandler1);
   }

   void sdkcommunication_RaiseCustomEventHandler1(object sender, CustomEventHandler1 e)
   {
      //Do something. 
   }
}

The information sended with the event you can get with e.Username and e.Directory. In this example they are strings where e.Username = johnsmith and e.Directory = localhost.

I hope somebody can use this information for their own code.

Comments

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.