C# Is this a case for delegation and callbacks? - c#

I have an object that handles the logging in of users. This object has a method called LoginPopUp(), which calls Login.show() to display the Login form/window.
The form/window is a seperate object. When a user enters their details and presses submit I want the form to pass data BACK to the calling object. The calling object (the object that handles loging in) will then validate the username and password. If the user is in the database it will close the window.
If the user is not in the database it will remain open and display "incorrect login". So I need a way for the calling object to pass information back to the login window to tell it it's failed.
Im a little confused on how to do this. Is this a case for callbacks and delegation? Whats the conventional solution to use in cases like this? As I'd imagine this happens a lot.
Comments appreciated.

You can do this with a delegate (aka callback). Have a delegate typed property of the login form that the caller can set. You can also do it with an event (which is also a delegate really) and have the login form expose an event that the caller can subscribe to before showing the form.
However, if the same action is always taken after login, then it might be more straightforward to do a direct call instead of using delegates.

Your approach will work.
Another simple option is to pass a reference to the user validator to the login window
make the validation function static.
to do what you want here is an ex.
Just create form1 with a text box and form2 with two text boxes and a button to run.
namespace TestApp
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public bool DoValidate(string username, string password)
{
MessageBox.Show(string.Format("I got called with {0} : {1}",username,password));
return true;
}
private void button1_Click(object sender, EventArgs e)
{
Form2 F = new Form2(DoValidate);
F.ShowDialog();
}
}
}
namespace TestApp
{
public partial class Form2 : Form
{
private Form2()
{
InitializeComponent();
}
public delegate bool LoginFn(string Uname, string pword);
private LoginFn m_CallFn;
public Form2(LoginFn del)
{
InitializeComponent();
m_CallFn = del;
}
private void cmdLogon_Click(object sender, EventArgs e)
{
if (!m_CallFn(txtUser.Text, txtPassword.Text))
{
MessageBox.Show("Fail");
}
else
{
MessageBox.Show("Good");
}
}
}
}

You could achive this in multiple ways
using delegate callbacks
using func delegate(inline anonymos methods)
using events
public class FormTest:Form
{
public delegate int validateLogin(string userID,string Password);
public validateLogin validate;
public event validateLogin validateEvent;
public void submitWithcallback()
{
string userId=string.Empty,pwd=string.Empty;
validate(userId, pwd);
}
public void submitWithFuncDelegate(Func<string,string,int> funcDelegate)
{
string userId = string.Empty, pwd = string.Empty;
funcDelegate(userId, pwd);
}
public void submitWithEvent()
{
string userId = string.Empty, pwd = string.Empty;
validateEvent(userId, pwd);
}
}
and invoke this from your class
public class Test
{
static int validate(string uid, string pwd)
{
//your validation code
return 1;
}
void testValidate()
{
Func<string, string, int> validateFunc = (uid, pwd) =>
{
//your validation code
return 1;
};
FormTest.validateLogin vDel = new FormTest.validateLogin(validate);
FormTest v1 = new FormTest();
v1.validate = new FormTest.validateLogin(vDel);
v1.submitWithcallback();
v1.submitWithFuncDelegate(validateFunc);
v1.validateEvent += new FormTest.validateLogin(validate);
//or with anonymous functions
v1.validateEvent += (string uid,string pwd)=>{
//your validation code
return 1;
};
v1.submitWithEvent();
}
}

expose event on Login form, like LoginSubmitted with event args that contain the login and password
expose method on Login form, like ShowLoginFailed()
subscribe to the LoginSubmitted event in the controlling object, and handle it by reading the login and password from the event args and checking the database
if login is successful, close Login, otherwise call ShowLoginFailed()

Callback/closures will work well here.
Maybe a snippet will help explain.
bool CheckUser(string user, string pass) { ... }
...
void ShowLogin(Func<string,string,bool> check)
{
var f = new LoginForm();
f.LoginClick += delegate
{
if (check(f.User, f.Pass))
{
f.Close();
}
};
f.ShowDialog();
}
Usage:
ShowLogin(CheckUser);

Related

C# pass delegates to different forms

i have a WinForms app that consists of several forms.
What I'm trying to achieve is to pass an event handler from a second form, to a third one, but i cannot achieve that. i get a casting error which i can't figure out how to overcome.
i would appreciate the help:
code + further explanation below:
This is a rough image of what is supposed to happen:
Form1 can create several forms (it also holds the methods that i want to pass) - which i can pass successfully on sub form creation.
the problem starts when i create form3 from within form2: i try to pass the event handler, but i get Error CS0029/CS0030 (casting errors)
what am i doing wrong and how to fix it?
EDIT:
what needs to happen? -- Form3 needs to control (send back data) to a Gui control placed in Form1
Code:
Form1:
public delegate void sendMessageToConsoleDelegate(string value);
public sendMessageToConsoleDelegate sendMessageToConsoleCallback;
public delegate void SetPlaceHolderDelegate(TextBox tb);
public SetPlaceHolderDelegate SetPlaceHolderCallback;
private void SetPlaceHolder(TextBox tb)
{
if (!tb.InvokeRequired)
{
if (!tb.Focused)
{
if (string.IsNullOrWhiteSpace(tb.Text))
tb.Text = tb.Tag.ToString();
return;
}
if (tb.Text == tb.Tag.ToString())
tb.Text = "";
return;
}
SetPlaceHolderDelegate call = new SetPlaceHolderDelegate(SetPlaceHolder);
tb.BeginInvoke(call, tb);
}
private void SendMessageToConsole(string msg)
{
if (!textBoxConsole.InvokeRequired)
{
textBoxConsole.AppendText(msg);
return;
}
sendMessageToConsoleDelegate call = new sendMessageToConsoleDelegate(SendMessageToConsole);
textBoxConsole.BeginInvoke(call, msg);
}
private void AddNewDeviceForm()
{
frmAddDevice add_device = new frmAddDevice(devicesDBPath);
add_device.sendMessageToConsole += SendMessageToConsole;
add_device.Show();
}
private void StartEdit()
{
frmEditDBs editdb = new frmEditDBs(devicesDBPath, commandsDBPath);
editdb.sendMessageToConsole += SendMessageToConsole;
editdb.SetPlaceHolder += SetPlaceHolder;
editdb.Show();
}
Form2 (frmEditDBs)
public delegate void EventHandler_sendMessageToConsole(string msg);
public event EventHandler_sendMessageToConsole sendMessageToConsole = delegate { };
public delegate void EventHandler_SetPlaceHolder(TextBox tb);
public event EventHandler_SetPlaceHolder SetPlaceHolder = delegate { };
private void EditDevice()
{
frmAddDevice edit_device = new frmAddDevice(devicesDBpath, current_device);
edit_device.sendMessageToConsole += sendMessageToConsole; ****<== This is the issue (same for the placeholder)****
edit_device.Show();
}
i get error CS0029
how can i pass the same delegate to other sub forms (e.g. frmAddDevice)?
Your question is how to C# pass delegates to different forms so that you can (for example) sendMessageToConsole to your MainForm from the other forms. In your code you state that this is the problem:
// This is the issue (same for the placeholder)****
edit_device.sendMessageToConsole += sendMessageToConsole;
When I look at your code, in essence you are trying to implement your own version of an Event Pattern. One solution to your issue would be to use a standard event pattern. Then intellisense will recognize your custom event delegate in the standard way:
FIRST you need to make the delegate and the inherited EventArgs class outside of your MainForm class:
namespace pass_delegates
{
public partial class MainForm : Form
{
}
// Make sure these are outside of any other class.
public delegate void SendMessageToConsoleEventHandler(object sender, SendMessageToConsoleEventArgs e);
public class SendMessageToConsoleEventArgs : EventArgs
{
public string Message { get; }
public SendMessageToConsoleEventArgs(string message)
{
Message = message;
}
}
}
Your frmAddDevice (shown here in minimal format) declares the delegate using the event keyword. Your other form frmEditDBs does exactly the same thing.
public partial class frmAddDevice : Form
{
public event SendMessageToConsoleEventHandler SendMessageToConsole;
public frmAddDevice(string devicesDBpath)
{
InitializeComponent();
}
protected virtual void OnSendMessageToConsole(SendMessageToConsoleEventArgs e)
{
SendMessageToConsole?.Invoke(this, e);
}
// Clicking the button will call this as a test.
private void btnSendTestMessage_Click(object sender, EventArgs e)
{
OnSendMessageToConsole(new SendMessageToConsoleEventArgs("Message received from 'Add Device Form'"));
}
}
A button in the MainForm code creates a new frmAddDevice like this:
frmAddDevice frmAddDevice = null;
// This handler in the Main Form creates the frmAddDevice form
private void btnFrmAddDevice_Click(object sender, EventArgs e)
{
if (frmAddDevice == null)
{
frmAddDevice = new frmAddDevice(devicesDBpath: "Some path");
// This was the problem. Not anymore ****
frmAddDevice.SendMessageToConsole += outputMessageToConsole;
}
frmAddDevice.Show();
}
private void outputMessageToConsole(object sender, SendMessageToConsoleEventArgs e)
{
textBoxConsole.AppendText(e.Message + Environment.NewLine);
}
If you do these things, you will achieve the functionality of sendMessageToConsole that your code is attempting to do. Try it out by downloading my sample from GitHub.
I think the main concept you don't understand is that delegate is "same level" as class, enum, struct etc. You need to declare it in some shared scope to make it accessible in both forms.
namespace ConsoleApp6
{
public delegate void TestDelegate();
public class ClassA
{
public TestDelegate delegateA;
}
public class ClassB
{
public TestDelegate delegateB;
}
internal class Program
{
static void Main(string[] args)
{
TestDelegate del = () => { };
var classA = new ClassA()
{
delegateA = del,
};
var classB = new ClassB()
{
delegateB = classA.delegateA
};
}
}
}
Or, if you want to keep it inside of the form, you need reference it by a class name the same way you would do with a type.
namespace ConsoleApp6
{
public class ClassA
{
public delegate void TestDelegate();
public TestDelegate delegateA;
}
public class ClassB
{
public ClassA.TestDelegate delegateB;
}
internal class Program
{
static void Main(string[] args)
{
ClassA.TestDelegate del = () => { };
var classA = new ClassA()
{
delegateA = del,
};
var classB = new ClassB()
{
delegateB = classA.delegateA
};
}
}
}
As was described previously, your "delegates" should be declared generically at the namespace of your project, not within a specific class so they are visible throughout your app. To do so, maybe make a separate file in your project for "MyDelegates" and may look something like:
using System.Windows.Forms;
namespace WinHelp1
{
// Create your own delegates outside of your classes that need to be publicly
// visible within your app or even protected if so needed.
public delegate void EventHandler_SendMessageToConsole(string msg);
public delegate void EventHandler_SetPlaceHolder(TextBox tb);
}
Now, in your form 1 that you want to define WHAT to do, do so based on the signatures matching appropriately
using System.Windows.Forms;
namespace WinHelp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void DoThisForConsole(string msg)
{
// whatever to do with string
}
public void DoThisForTextBox(TextBox tb)
{
// whatever to do with textbox
}
private void Btn2_Click(object sender, System.EventArgs e)
{
var f2 = new Form2();
f2.SendMessageToConsole += DoThisForConsole;
f2.SetPlaceHolder += DoThisForTextBox;
f2.ShowDialog();
// OR, if using the PARAMETERIZED for pass-through to call
// when form2 calls form 3
var f2b = new Form2( DoThisForConsole, DoThisForTextBox );
f2b.ShowDialog();
}
private void Btn3_Click(object sender, System.EventArgs e)
{
var f3 = new Form3();
f3.SendMessageToConsole += DoThisForConsole;
f3.SetPlaceHolder += DoThisForTextBox;
f3.ShowDialog();
}
}
}
First, form3 since that will just have the direct event handlers, and you can invoke however within form 3
using System.Windows.Forms;
namespace WinHelp1
{
public partial class Form3 : Form
{
// now, for each form you want to USE them on...
public event EventHandler_SendMessageToConsole SendMessageToConsole;
public event EventHandler_SetPlaceHolder SetPlaceHolder;
public Form3()
{
InitializeComponent();
}
}
}
Now, in your form 2, is a bit different. Since you want to make available for form2 to call form3 with the same event handler, just add those event handlers as parameters to the constructor class. Then you can preserve them in that form, but at the same time, self-register them as in the var f2b = new Form2 of the second button click event. Then use those preserved values when form2 needs to call form3
using System.Windows.Forms;
namespace WinHelp1
{
public partial class Form2 : Form
{
// now, for each form you want to USE them on...
public event EventHandler_SendMessageToConsole SendMessageToConsole;
public event EventHandler_SetPlaceHolder SetPlaceHolder;
// now, for each form you want to USE them on...
public EventHandler_SendMessageToConsole passThroughForMessage;
public EventHandler_SetPlaceHolder passThroughForTextBox;
public Form2()
{
InitializeComponent();
}
public Form2(EventHandler_SendMessageToConsole forSendMsg, EventHandler_SetPlaceHolder forPlaceHolder ) : this()
{
// preserve into properties in-case you need to call form 3
passThroughForMessage = forSendMsg;
passThroughForTextBox = forPlaceHolder;
// and the constructor can auto-set for itself so IT can notify as well
if( forSendMsg != null )
SendMessageToConsole += forSendMsg;
if( forPlaceHolder != null )
SetPlaceHolder += forPlaceHolder;
}
private void Btn3_Click(object sender, System.EventArgs e)
{
var f3 = new Form3();
// and the constructor can auto-set for itself so IT can notify as well
if (passThroughForMessage != null)
f3.SendMessageToConsole += passThroughForMessage;
if (passThroughForTextBox != null)
f3.SetPlaceHolder += passThroughForTextBox;
f3.ShowDialog();
}
}
}
Remember, parameters can be practically anything, and you can have a variable stored in a property just like anything else... as long as it matches the respective type.
Then, from form3, either instance will invoke back to whatever the root instance method may be.

how to pass a form as a parameter?

First I know there are already answer for this question but most solution seems complicated for nothing.
Situation :
I have a form called frm1. I want to pass it as parameter
myfunc(ref frm1)
I would then do
private void myfunc(ref Form frm1)
It says : frm1 is a type but is used as a variable.
My reason for doing this is because depending on choice I pass my form to one of either two functions which fills it differently.
Problem :
However I cannot pass as argument my form. However I can pass other controls like button in the same way. How can I do this simply with the form, without interface etc...
There is something wrong with the way you are passing the parameter in. Are you definitely passing in the instance and not the type?
Here's a working example.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.Name = "form";
Form f = this;
doSomethingWithForm(f);
}
private void doSomethingWithForm(Form f)
{
Console.WriteLine(f.Name);
}
}
I have created one function. I think it will help you. I am using this in my practice.
-->function below:
public void showForm(Form _form, Form _main) {
if (_main != null)
{
if (_main.ActiveMdiChild != null)
{
_main.ActiveMdiChild.Close();
}
_form.MdiParent = _main;
_form.Activate();
_form.Show();
}
else
{
_form.Activate();
_form.ShowDialog();
}
-->how to use it:
objLib.showForm(new frmMain(), null);
OR
objLib.showForm(new frmNewspaper(), this);
Thank You
I will add to kenjara's answer.
// For example: change color of the form - from some other method
private void Form_Load(object sender, EventArgs e)
{
ChS = new ChangeSomething();
ChS.ChangeBackColor(this);
}
public class ChangeSomething
{
public void ChangeBackColor(Form form)
{
form.BackColor = System.Drawing.Color.Black;
return;
}
}
Tested VS2022 / .NET4.8 / Windows Forms

C# Multiple class events

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
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.
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;
}
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.
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.

passing value from another class to textbox in form?

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?
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());
}
}
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);
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.

Unable to SET value from another class

Im trying to set LabelStatus's text to a message in the class but it doesn't work.
Here's my code:
Class:
public bool openConnection()
{
SetStatus("Connecting to " + Server);
//Mysql code
}
private void SetStatus(string msg)
{
Form1 form = new Form1();
form.SetStatus(msg);
}
Form1:
public void SetStatus(string status)
{
labelStatus.Text = _status;
}
I'm fairly new to C# (php guy) and for the life of me can't figure out what I am doing wrong
Try calling the ShowDialog or Show Method on your form
private void SetStatus(string msg)
{
Form1 form = new Form1();
form.SetStatus(msg);
form.ShowDialog(this);
}
looks like you are setting the member variable and not the function's parameter.
//try something like this
this._status = status;
this.labelStatus.Text = this._status;
When setting labelStatus.Text, you're not setting it with the parameter you passed to SetStatus(string). It seems like you accidentally used a data member instead.
Look at the names : try to make them same, see
labelStatus.Text = **status**;
From your code, I think your class is change the status label of form label. To change form label text you need object of already opened form. define variable for form in your class.
public class ConnectionCheck
{
private Form myForm;
public void ConnectionCheck(Form form)
{
myForm = form;
}
public bool openConnection()
{
SetStatus("Connecting to " + Server);
//Mysql code
}
private void SetStatus(string msg)
{
//Call method to change label text
myForm .SetStatus(msg);
}
}
Pass form1 object at the time of ConnectionCheck object creation from from1 codebehind(form1.cs).
ConnectionCheck connection = new ConnectionCheck(this);
And Also, change _status to parameter variable.
public void SetStatus(string status)
{
labelStatus.Text = status;
}

Categories

Resources