Global delegate to subscribe to - c#

I have Multiple class that need to subscribe to a delegate.
How is that possible? If I do declare delegate in my mainForm is that well coded?
Example code:
internal delegate void DEL_SetSingleVal(Single value);
public partial class Form1 : Form
{
Single Data;
ClasswithDel ClassDelegate;
TryToAccess AccessDelegate;
public Form1()
{
InitializeComponent();
ClassDelegate = new ClasswithDel();
AccessDelegate = new TryToAccess();
ClassDelegate.SetValCbk += new DEL_SetSingleVal(SetValCbkFn);
ClassDelegate.SetValCbk += new DEL_SetSingleVal(AccessDelegate.SetValCbkObj2Fn);
}
internal void SetValCbkFn(Single value)
{
Data = value;
}
private void SetValueLabel(String value)
{
label1.Text = value;
}
private void button1_Click(object sender, EventArgs e)
{
ClassDelegate.SetValue(Convert.ToSingle(textBox1.Text));
}
}
public class TryToAccess
{
private Single Data2;
internal void SetValCbkObj2Fn(Single value)
{
Data2 = value;//value come from From1
}
}
public class ClasswithDel
{
internal DEL_SetSingleVal SetValCbk;
public void SetValue(Single valuesent)//value to dispatch to Form1 and TryToAccess
{
SetValCbk(valuesent);
}
}
Is this looking good? Thanks for help!

Related

C#-Winforms-How to use instance objects in different subforms?

I have a "MainForm" and a "GraphicsForm". Clicking "New" on the main form, a "GraphicsForm" will be created.
The problem is that when I create multiple "GraphicsForm", and when I want to save the content of one of the "GraphicsForm", I need to clicking "Save" on the "MainForm" and the program will save the content of the active "GraphicsForm" to a file, I don't know how to pass the content of this "GraphicsForm" to "MainForm" for storage.
MainForm.cs
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
private ToolStripMenuItem _winMenuItem = new ToolStripMenuItem();
private GraphicsForm _graphicsForm;
private int _counter = 1;
private void New_Click(objec sender, EventArgs e)
{
_winMenuItem.Name = "Win";
_winMenuItem.Text = "Windows";
int item = MainMenuStrip.Items.IndexOf(_winMenuItem);
if (item == -1)
{
MainMenuStrip.Items.Add(_winMenuItem);
MainMenuStrip.MdiWindowListItem = _winMenuItem;
}
_graphicsForm = new GraphicsForm();
_graphicsForm.Name = string.Concat("Win_", _counter.ToString());
_graphicsForm.Text = _graphicsForm.Name;
_graphicsForm.MdiParent = this;
_graphicsForm.Show();
_graphicsForm.WindowState = FormWindowState.Maximized;
_counter++;
}
private void Save_Click(object sender, EventArgs e)
{
... // Problem here
}
private void Open_Click(object sender, EventArgs e)
{
... // Problem here
}
}
GraphicsForm.cs
public partial class GraphicsForm : Form
{
//StorageDoc is a class to manage all the graphics drawn by the user in the form.
private StorageDoc _storageDoc = new StotageDoc();
public GraphicsForm()
{
InitializeComponent();
}
private Canvas_MouseDown()
{
}
private Canvas_Paint()
{
}
...
Because MainForm is a MDI form, it is easy to use ActiveMdiChild to get the active child form.
class MainForm : Form
{
public void OnSaveButtonClick(object sender, EventArgs e)
{
if(ActiveMdiChild is GraphicsForm g)
Save(g);
}
}
I'm sure this has been answered before but basically, you pass in an instance of the 'data storage' to the new form.
interface ISaveForm
{
void Save();
}
class MainForm
{
private DataStorage _dataStorage;
private ICollection<ISaveForm> _forms = new List<ISaveForm>();
public void OnNew()
{
var subForm = new GraphicsForm(_dataStorage);
subForm.Show();
_forms.Add(subForm);
}
public void OnSave()
{
foreach(var form in _forms)
{
form.Save();
}
}
}
class GraphicsForm : Form,ISaveForm
{
private DataStorage _dataStorage;
public GraphicsForm(DataStorage dataStorage)
{
_dataStorage = dataStorage;
}
public void Save()
{
}
}

Passing values to User Control from Form

I've created User Control in my WFA (Windows Form Application) and I want to pass value from my MainForm.cs to UserControl.cs but I have no idea on how to do that. Here are my values I want to pass to the UserControl.cs
public partial class MainForm : Form
{
private void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
if (ProcOpen)
{
//THESE
int vlInt = m.ReadByte("base+007C1DAC,0x14,0x4");
int roomID = m.ReadByte("base+003CA150,0x0");
double diffValue = m.ReadDouble("base+007B4A3C,0x0,0x2c,0x10,0x7ec,0x300");
}
}
}
To
public partial class FirstCustomControl : UserControl
{
public FirstCustomControl()
{
InitializeComponent();
}
private void FirstCustomControl_Load(object sender, EventArgs e)
{
//GET THE VALUES HERE
}
}
you can define a property for your UC then set the property from the parent;
public partial class FirstCustomControl : UserControl
{
public static dynamic vlInt;
public static dynamic roomID;
public static dynamic diff;
public FirstCustomControl()
{
InitializeComponent();
}
public void NotifyValueChanged(){
label1.text = vlInt.ToString();
label2.text = roomID.ToString();
label3.text = diff.ToString();
}
private void FirstCustomControl_Load(object sender, EventArgs e)
{
}
}
Then in your MainForm
public partial class MainForm : Form
{
private void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
if (ProcOpen)
{
//THESE
FirstCustomControl.vlCount = m.ReadByte("base+007C1DAC,0x14,0x4");
FirstCustomControl.roomID = m.ReadByte("base+003CA150,0x0");
FirstCustomControl.diff = m.ReadDouble("base+007B4A3C,0x0,0x2c,0x10,0x7ec,0x300");
firstCustomControl1.NotifyValueChanged();
}
}
}

C# Use instance of a class made in Form 1 in Form 2

I want to Use an instance of a class made in Form 1 in Form 2 (i changed it to a list for simplicity of example code:
Not only that, I want Form 2 to be able to modify it (Clear it at some point).
The advice I got was this, although I was not told how due to "no spoonfeeding allowed"
namespace automationControls.FileTime
{
public class Form_Main : Form
{
public List<string> folderList; //<---- i want to access this.....
private void button_showForm2_Click(object sender, EventArgs e)
{
Form_Log ConfirmBoxForm = new Form_Log(this);
ConfirmBoxForm.Show();
}
}
//form_Main opens form_Log
namespace automationControls.FileTime
{
public partial class Form_Log : Form
{
public Form_Log(Form_Main _f1)
{
InitializeComponent();
}
private void Form1_FormClosing(Object sender, FormClosingEventArgs e)
{
How.Do.I.AccessForm_Main.folderList.Clear();//<---- ............. in this function
}
}
}
Answered:In the constructor of Form_Log, store the reference to _f1 somewhere you can access it from elsewhere in Form_Log
Why don't you use the constructor that you have already added your form?
private Form_Main _mainForm;
public Form_Log(Form_Main _f1)
{
InitializeComponent();
_mainForm = _f1;
}
private void Form1_FormClosing(Object sender, FormClosingEventArgs e)
{
var myList = _mainForm.folderList;
}
Try This,
public class Form_Main : Form
{
public List<string> folderList; //<---- i want to access this.....
private void button_showForm2_Click(object sender, EventArgs e)
{
Form_Log ConfirmBoxForm = new Form_Log(this);
ConfirmBoxForm.Show();
}
}
Form log :
public partial class Form_Log : Form
{
private Form_Main _mainForm;
public Form_Log(Form_Main _f1)
{
InitializeComponent();
_mainForm = _f1;
}
private void Form1_FormClosing(Object sender, FormClosingEventArgs e)
{
_mainForm.folderList.Clear();
}
}
I don't know how advanced is your project but in this situation i would use delegates. Here is how i would do it:
public delegate void ModifyCollectionHandler(string parameter);
public delegate void ClearCollectionHandler();
public partial class Form1 : Form
{
public List<string> folderList;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Form2 form = new Form2()
form.ClearItem+=form_ClearItem;
form.AddItem+=form_AddItem;
form.DeleteItem+=form_DeleteItem;
}
void form_DeleteItem(string parameter)
{
if (folderList == null)
return;
folderList.Remove(parameter);
}
void form_AddItem(string parameter)
{
if (folderList == null)
folderList = new List<string>();
folderList.Add(parameter);
}
void form_ClearItem()
{
if (folderList != null)
folderList.Clear();
}
}
public partial class Form2 : Form
{
public event ModifyCollectionHandler AddItem;
public event ModifyCollectionHandler DeleteItem;
public event ClearCollectionHandler ClearItem;
public Form2()
{
InitializeComponent();
}
private void Form2_FormClosing(object sender, FormClosingEventArgs e)
{
if (ClearItem != null)
ClearItem();
}
}
I hope I helped you :)
Best regards
in the Form1 put this :
public static List<string> folderList;
you can simply call it from any form ex:Form2 like this :
From1.folderList.Clear();

C#: String as parameter to event?

I have a GUI-thread for my form and another thread that computes things.
The form has a richtTextBox. I want the worker-thread to pass strings to the form, so that every string is displayed in the textbox.
Everytime a new string is generated in the worker thread I call an event, and this should now display the string.
But I don't know how to pass the string! This is what I tried so far:
///// Form1
private void btn_myClass_Click(object sender, EventArgs e)
{
myClass myObj = new myClass();
myObj.NewListEntry += myObj_NewListEntry;
Thread thrmyClass = new Thread(new ThreadStart(myObj.ThreadMethod));
thrmyClass.Start();
}
private void myObj_NewListEntry(Object objSender, EventArgs e)
{
this.BeginInvoke((MethodInvoker)delegate
{
// Here I want to add my string from the worker-thread to the textbox!
richTextBox1.Text += "TEXT"; // I want: richTextBox1.Text += myStringFromWorkerThread;
});
}
///// myClass (working thread...)
class myClass
{
public event EventHandler NewListEntry;
public void ThreadMethod()
{
DoSomething();
}
protected virtual void OnNewListEntry(EventArgs e)
{
EventHandler newListEntry = NewListEntry;
if (newListEntry != null)
{
newListEntry(this, e);
}
}
private void DoSomething()
{
///// Do some things and generate strings, such as "test"...
string test = "test";
// Here I want to pass the "test"-string! But how to do that??
OnNewListEntry(EventArgs.Empty); // I want: OnNewListEntry(test);
}
}
Like this
public class NewListEntryEventArgs : EventArgs
{
private readonly string test;
public NewListEntryEventArgs(string test)
{
this.test = test;
}
public string Test
{
get { return this.test; }
}
}
then you declare your class like this
class MyClass
{
public delegate void NewListEntryEventHandler(
object sender,
NewListEntryEventArgs args);
public event NewListEntryEventHandler NewListEntry;
protected virtual void OnNewListEntry(string test)
{
if (NewListEntry != null)
{
NewListEntry(this, new NewListEntryEventArgs(test));
}
}
}
and in the subscribing Form
private void btn_myClass_Click(object sender, EventArgs e)
{
MyClass myClass = new MyClass();
myClass.NewListEntry += NewListEntryEventHandler;
...
}
private void NewListEntryEventHandler(
object sender,
NewListEntryEventArgs e)
{
if (richTextBox1.InvokeRequired)
{
this.Invoke((MethodInvoker)delegate
{
this.NewListEntryEventHandler(sender, e);
});
return;
}
richTextBox1.Text += e.Test;
}
I've taken the liberty of making the NewListEntryEventArgs class immutable, since that makes sense. I've also partially corrected your naming conventions, simplified and corrected where expedient.
You need to create a new class by inheriting off EventArgs.
Create your own version of the EventArgs.
Do it like this:
public class MyEventArgs : EventArgs
{
public string MyEventString {get; set; }
public MyEventArgs(string myString)
{
this.MyEventString = myString;
}
}
Then in your code replace the EventArgs with MyEventArgs and create an MyEventArgs object with your string in it.
Then you can access it by using the MyEventArgs instance .MyEventString.
So you would do something like this:
///// myClass (working thread...)
class myClass
{
public event EventHandler NewListEntry;
public void ThreadMethod()
{
DoSomething();
}
protected virtual void OnNewListEntry(MyEventArgs e)
{
EventHandler newListEntry = NewListEntry;
if (newListEntry != null)
{
newListEntry(this, e);
}
}
private void DoSomething()
{
///// Do some things and generate strings, such as "test"...
string test = "test";
OnNewListEntry(new MyEventArgs(test));
}
}
And in your form:
private void myObj_NewListEntry(Object objSender, MyEventArgs e)
{
this.BeginInvoke((MethodInvoker)delegate
{
// Here I want to add my string from the worker-thread to the textbox!
richTextBox1.Text += e.MyEventString;
});
}
In general you need to inherit EventArgs and add a string property, and then make your event of type EventHandler<YourEventArgs>, but that is a classic case for the BackgroundWorker.
Sample here:
http://msdn.microsoft.com/en-us/library/cc221403(v=vs.95).aspx
and here:
C# backgroundWorker reports string?

Access EventHandler Between Two Forms

I wants to access Form1's EventHandler In Form2
Form1 EventHandler is:-
private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
How to achieve it?.
You are doing something wrong.
If you want to expose functionality, you should create a public method/function to do so. You can call this from your event handler and from your other form.
Answer updated by your question in comment, I didn't checked that it works fine may be there is a bug with it:
It's useful when you have a similar event, Also you can pass different EventArgs, easiest way is to have a different Property which determines each form and add event in their set methods but bellow is general
public abstract class FormBase : Form
{
public virtual event EventHandler MyEventHandler;
}
public class Form3 : FormBase
{
public override event EventHandler MyEventHandler;
Form2 instance;
public Form3()
{
instance = Form2.Instance;
instance[this.GetType().ToString()] = this;
// or
//instance["Form3"] = this;
}
private void dataGridView1_CellEndEdit(object sender, EventArgs e)
{
// todo
if (MyEventHandler != null)
MyEventHandler(this, e);
}
}
public class Form2
{
Dictionary<string, FormBase> dic = new Dictionary<string,FormBase>();
public FormBase this[string index]
{
get
{
FormBase retVal = null;
if (dic.TryGetValue(index, out retVal))
return retVal;
return null;
}
set
{
FormBase retVal = null;
if (value == null)
return;
if (dic.TryGetValue(index, out retVal))
{
try
{
value.MyEventHandler -= MyEventHandler1;
}
catch
{
}
retVal = value;
retVal.MyEventHandler += MyEventHandler1;
return;
}
value.MyEventHandler += MyEventHandler1;
dic.Add(index, value);
}
}
private static Form2 instance;
public static Form2 Instance
{
get
{
if (instance == null)
{
instance = new Form2();
}
return instance;
}
}
private Form2()
{
}
private void MyEventHandler1(object sender, EventArgs e)
{
}
}
Change the access modifier to public instead of private.
Another option is to parse the eventhandler on Form1 to Form2:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
DataGridViewCellEventHandler dataGridViewCellEventHandler = new DataGridViewCellEventHandler(this.dataGridView1_CellEndEdit);
this.dataGridView1.CellEndEdit += dataGridViewCellEventHandler;
Form2 form2 = new Form2();
form2.CellEndEdit += dataGridViewCellEventHandler;
}
private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
//Do something
}
}
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
public event DataGridViewCellEventHandler CellEndEdit
{
add { dataGridViewOnForm2.CellEndEdit += value; }
remove { dataGridViewOnForm2.CellEndEdit -= value; }
}
}
This does however require that Form1 has access to Form2

Categories

Resources