c# invoking delegate function throws System.NullReferenceException - c#

I have two forms, a FormMain, and a FormInputTagName. The FormMain uses FormInputTagName as a dialog to get a string from the user.
For this I've declared a delegate in FormInputTagName, here's the code:
public partial class FormInputTagName : Form
{
public delegate void ResultDelegate(string tagName);
public ResultDelegate _resultDelegate;
public void InputTagName(ResultDelegate resultDelegate)
{
this.ShowDialog();
_resultDelegate = resultDelegate;
}
private void Ok_Click(object sender, EventArgs e)
{
this.Hide();
_resultDelegate(textBoxElementTagName.Text);
}
}
Just in case, _resultDelegate is public, but it doesn't solve the problem.
In the FormMain, I have a method, with the signature as delegate declares:
public void AddElement(string tagName)
{
MessageBox.Show(tagName);
}
And a code (also in FormMain), that calls FormInputTagName passing AddElement as a delegate instance to it:
private void addToolStripMenuItem_Click(object sender, EventArgs e)
{
FormInputTagName inputForm = new FormInputTagName();
inputForm.InputTagName(new FormInputTagName.ResultDelegate(AddElement));
}
And when I run the program and type some text into textBoxElementTagName and click Ok button, it throws System.NullReferenceException at line
_resultDelegate(textBoxElementTagName.Text);
What can be a cause? Can it be that I call delegate in synchronous manner and should I call it using BeginInvoke / EndInvoke ?
And one more thing - if I do not save delegate into a class member _resultDelegate, but call it immediately, like that
public void InputTagName(ResultDelegate resultDelegate)
{
this.ShowDialog();
resultDelegate("qwer");
}
it works fine and calls AddElement function.

Related

How to call a method from another class in a button click event?

I'm trying to call a non-static method (LoadingListBox) in my class (ListDisplay) from a button click event in my AddTask class.
namespace Project
{
public partial class ListDisplay : Form
{
public void LoadingListBox()
{
//code
}
}
}
namespace Project
{
public partial class AddTask : Form
{
private void btnSubmit_Click(object sender, EventArgs e)
{
//code
//I want to call LoadingListBox here
}
}
}
I have tried creating an instance of ListDisplay by doing ListDisplay listDisplayI = new ListDisplay(); and then writing ListDisplay.LoadingListBox();
There were no errors with this code but when debugging the flow of control wouldn't go to the method it just carried on past it.
I have also tried doing what the answer suggests from this question:
Call a public method of main class from another class
But that comes up with an error as I can't overload the btnSubmit_Click method as the Designer freaked out. So I created a new method that had all of the code of btnSubmit_Click called public static void addingTask(ListDisplay) but I then had to create an instance of ListDisplay in order to put it as an argument in the btnSubmit_Click method hence ending up with two instances which is not what I want (due to answer of question).
So now I have come up with nothing and would appreciate any help you could give in order to call this LoadingListBox method.
Thanks!
Your two choices are based on whether or not you want a new instance of ListDisplay when you click the button or not.
Option 1:
namespace Project
{
public partial class AddTask : Form
{
private void btnSubmit_Click(object sender, EventArgs e)
{
var ld = new ListDisplay();
ld.Show();
ld.LoadingListBox();
}
}
}
Option 2:
namespace Project
{
public partial class AddTask : Form
{
private ListDisplay _ld;
public AddTask(ListDisplay ld)
{
_ld = ld;
}
private void btnSubmit_Click(object sender, EventArgs e)
{
_ld.LoadingListBox();
}
}
}

C# Run a method inside serialport_datareceived Event

I want to run a method inside serialport_DataReceived event.
public void Draw(byte[] data);
private void myPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
this.Invoke(new EventHandler(DrawingAudioData(data)));
}
This is not work. It gives an error that say "Method name expected". What can i do?
Try
public delegate void Draw(byte[] data);
private void myPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
this.Invoke(new Draw(DrawingAudioData), data);
}
Seems to me that the DrawingAudioData passed to Invoke does not have EventHandler signature. Also you should pass the method Name to the delegate constructor.
The DrawingAudioData method should have the signature that matches the Draw delegate:
public void DrawingAudioData(byte[] data) {
More information about Event Handler here.
More information about the Delegate and Invoke method here.

Call Class Method from other Class not working

I'm trying to call methods from class "Form1" from an other class.
Here's my Code
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
MessageBox.Show("loaded");
orders.ObjectForScripting = new ScriptInterface();
}
private void webBrowser2_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) { }
private void button1_Click_1(object sender, EventArgs e) { }
}
[System.Runtime.InteropServices.ComVisibleAttribute(true)]
public class ScriptInterface
{
public void callMe(string currid)
{
MessageBox.Show(currid);
// the following throws security error
Form1.webBrowser2.Navigate("http://www.mywebpage.com/client/index.php?id="+currid);
}
}
}
INFO: I have 2 WebBorwsers. I'm catching events from webBrowser1 for updating webBrowser2.
My problem is, that i cannot call the webbrowser2 methods outside from Form1.
Any Ideas how i can solve this problem?
Your WebBrowser components are not static (this is a good thing), therefore you cannot refer to them directly off of Form1 as your code sample is attempting to do. You must obtain a reference to a Form1 instance and then you can call methods on them so long as they are marked public. Depending on your needs it is probably even better to just pass along a reference directly to your WebBrowser components
Perhaps something like this:
orders.ObjectForScripting = new ScriptInterface(this.webBrowser2);
...
public class ScriptInterface
{
private WebBrowser _browser;
public ScriptInterface(WebBrowser browser)
{
_browser = browser;
}
public void callMe(string currid)
{
_browser.Navigate("http://www.mywebpage.com/client/index.php?id="+currid);
}
}
Form1 in:
Form1.webBrowser2.Navigate(...)
Is not an object, but it is your type. You need to create an instance of your class, or if you prefer, create an object to be able to call it's method:
Form1 form = new Form1();
form.webBrowser2.Navigate(...)
On top, your method are flagged private, which mean they can only be call from inside your instanced. You should flag them public if you want other object to be able to call them.
public void webBrowser2_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) { ... }
Or if you don't want to create an instance, you can declare this method as being static
public static void webBrowser2_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) { ... }
But you won't be able to access the fields that this class define unless they are static too.

Invoking EventHandler generic, TargetParameterCountException

I have a DirectoryMonitor class which works on another thread.
It has the following events declared:
public class DirectoryMonitor
{
public event EventHandler<MonitorEventArgs> CreatedNewBook;
public event EventHandler ScanStarted;
....
}
public class MonitorEventArgs : EventArgs
{
public Book Book { get; set; }
}
There is a form using that monitor, and upon receiving the events, it should update the display.
Now, this works:
void DirectoryMonitor_ScanStarted(object sender, EventArgs e)
{
if (InvokeRequired)
{
Invoke(new EventHandler(this.DirectoryMonitor_ScanStarted));
}
else {...}
}
But this throws TargetParameterCountException:
void DirectoryMonitor_CreatedNewBook(object sender, MonitorEventArgs e)
{
if (InvokeRequired)
{
Invoke(new EventHandler<MonitorEventArgs>(this.DirectoryMonitor_CreatedNewBook));
}
else {...}
}
What am I missing?
The Invoke method excepts to receive a System.Delegate instance which can be invoked without passing any additional parameters. The delegate created by using DirectoryMonitor_ScanStarted requires 2 parameters and hence you get the exception when it's used.
You need to create a new delegate which wraps the call and arguments together.
MethodInvoker del = () => this.DirectoryMonitor_ScanStarted(sender,e);
Invoke(del);
You're missing the parameters:-
void DirectoryMonitor_ScanStarted(object sender, MonitorEventArgs e)
{
if (InvokeRequired)
{
Invoke(new EventHandler<MonitorEventArgs>(DirectoryMonitor_ScanStarted), sender, e);
}
else {...}
}
For reasons not clear to me (probably due to COM legacy) it's permissible to omit parameters when using a generic event, but not when using a user defined EventArg type.

How to subscribe to other class' events in C#?

A simple scenario: a custom class that raises an event. I wish to consume this event inside a form and react to it.
How do I do that?
Note that the form and custom class are separate classes.
public class EventThrower
{
public delegate void EventHandler(object sender, EventArgs args) ;
public event EventHandler ThrowEvent = delegate{};
public void SomethingHappened() => ThrowEvent(this, new EventArgs());
}
public class EventSubscriber
{
private EventThrower _Thrower;
public EventSubscriber()
{
_Thrower = new EventThrower();
// using lambda expression..could use method like other answers on here
_Thrower.ThrowEvent += (sender, args) => { DoSomething(); };
}
private void DoSomething()
{
// Handle event.....
}
}
Inside your form:
private void SubscribeToEvent(OtherClass theInstance) => theInstance.SomeEvent += this.MyEventHandler;
private void MyEventHandler(object sender, EventArgs args)
{
// Do something on the event
}
You just subscribe to the event on the other class the same way you would to an event in your form. The three important things to remember:
You need to make sure your method (event handler) has the appropriate declaration to match up with the delegate type of the event on the other class.
The event on the other class needs to be visible to you (ie: public or internal).
Subscribe on a valid instance of the class, not the class itself.
Assuming your event is handled by EventHandler, this code works:
protected void Page_Load(object sender, EventArgs e)
{
var myObj = new MyClass();
myObj.MyEvent += new EventHandler(this.HandleCustomEvent);
}
private void HandleCustomEvent(object sender, EventArgs e)
{
// handle the event
}
If your "custom event" requires some other signature to handle, you'll need to use that one instead.

Categories

Resources