I have different Labels on my Form1 and want to change the text of a single Label using the same method.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Class1 change = new Class1();
change.ChangeLabelText();
}
public void ChangeLabel(string msg, Label label)
{
if (label.InvokeRequired)
label.Invoke(new MethodInvoker(delegate { label.Text = msg; }));
else
label.Text = msg;
}
}
how can i pass label1 or label2 as i need?
class Class1
{
public void ChangeLabelText()
{
Form1 frm1 = new Form1();
frm1.ChangeLabel("Surname", label2);
}
}
label2 is underlined of red: NOT EXIST IN THE ACTUAL CONTEST
I dont know what is the context in which you are trying to change the label... however I have a few observations seeing your sample code.
First of all, to your question, one of the approaches could be as follows,
private void button1_Click(object sender, EventArgs e)
{
Class1 change = new Class1(this);
change.ChangeLabelText();
}
public void ChangeLabel(string msg, Label label)
{
if (label.InvokeRequired)
label.Invoke(new MethodInvoker(delegate { label.Text = msg; }));
else
label.Text = msg;
}
// dont allow UI elements to be accessed directly from outide
public string Fullname
{
get
{
return label1.Text;
}
set
{
label1.Text = value;
}
}
// dont allow UI elements to be accessed directly from outide
public string Surname
{
get
{
return label2.Text;
}
set
{
label2.Text = value;
}
}
You see that object of Class1 gets reference to the Form1.
Inside Class1.ChangeLabelText you may do something like the following,
class Class1
{
Form1 _mainForm;
public Class1(Form1 form)
{
_mainForm = form;
}
public void ChangeLabelText()
{
//Form1 frm1 = new Form1();
//frm1.ChangeLabel("Surname", label2);
_mainForm.Surname = "Surname";
}
}
Observations after seeing your sample
It is a good practice not to expose/allow UI elements to be accessed by non-owner (Form1 is the owner in this case)
In button1_Click, you are already in a Form1 instance (object), however in ChangeLabelText, you are trying to create another instance of Form1.
Hope this helps you.
Another approach is to make Class1 raise an Event with the Name of the Label and the String to change it to. Your Form will receive the event, find the Label itself, and update the value. This way Class1 never needs a reference to Form1 or any of the Labels. It's still a bad design as you need to know the name of the Label, but this is the direction you went down anyways.
Here's what Class1 would look like:
public class Class1
{
public delegate void dlgChangeLabel(string lblName, string newValue);
public event dlgChangeLabel ChangeLabel;
public void ChangeLabelText()
{
if (ChangeLabel != null)
{
ChangeLabel("label2", "SurName");
}
}
}
Back in Form1, we need to subscribe to the ChangeLabel() event when we create our instance of Class1:
public partial class Form1 : Form
{
private void button1_Click(object sender, EventArgs e)
{
Class1 change = new Class1();
change.ChangeLabel += Change_ChangeLabel;
change.ChangeLabelText();
}
private void Change_ChangeLabel(string lblName, string newValue)
{
// see if we have a Label with the desired name:
Control[] matches = this.Controls.Find(lblName, true);
if (matches.Length > 0 && matches[0] is Label)
{
Label lbl = (Label)matches[0];
ChangeLabel(newValue, lbl); // update it in a thread safe way
}
}
private void ChangeLabel(string msg, Label label)
{
if (label.InvokeRequired)
label.Invoke(new MethodInvoker(delegate { label.Text = msg; }));
else
label.Text = msg;
}
}
Alternate version showing the creation of Class1 and wiring up of its Event during Form Load() so it's not attached to the Button handler:
public partial class Form1 : Form
{
private Class1 change = new Class1();
private void Form1_Load(object sender, EventArgs e)
{
change.ChangeLabel += Change_ChangeLabel;
}
private void Change_ChangeLabel(string lblName, string newValue)
{
Control[] matches = this.Controls.Find(lblName, true);
if (matches.Length > 0 && matches[0] is Label)
{
Label lbl = (Label)matches[0];
ChangeLabel(newValue, lbl);
}
}
private void ChangeLabel(string msg, Label label)
{
if (label.InvokeRequired)
label.Invoke(new MethodInvoker(delegate { label.Text = msg; }));
else
label.Text = msg;
}
}
Now you simply need to raise that event somehow in Class1. Just make sure it has a subscriber (is not null) before you raise it:
// in Class1
private void Foo()
{
if (ChangeLabel != null)
{
ChangeLabel("label2", "SurName");
}
}
You need to pass label as a parameter in your method
class Class1
{
public void ChangeLabelText(Label lbl)
{
Form1 frm1 = new Form1();
frm1.ChangeLabel("Surname", lbl);
}
}
And in your button click -
change.ChangeLabelText(label2);
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Class1 change = new Class1();
change.ChangeLabelText(this);
}
public void ChangeLabel(string msg, Label label)
{
if (label.InvokeRequired)
label.Invoke(new MethodInvoker(delegate { label.Text = msg; }));
else
label.Text = msg;
}
}
class Class1
{
public void ChangeLabelText(System.Windows.Forms.Form form)
{
if(form != null)
{
var labelIdWhoseTextNeedsToChange = "label2"; // Or any dynamic logic to determine which label will have to be updated.
var labelControl = form.Controls.Find(labelIdWhoseTextNeedsToChange, false);
if(labelControl != null)
{
form.ChangeLabel("Surname", labelControl);
}
}
}
}
Related
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()
{
}
}
I'm stuck with the following thing.
I want to change the panel color from another Form(ColorForm).
Is it possible?
Code From the MainForm:
public void upperpanel_Paint(object sender, PaintEventArgs e)
{
}
I don't know how to access that upperpanel_Paint in my ColorForm.
I'm opening ColorForm From SettingsForm
Mainform > SettingsForm > ColorForm
public partial class SettingsForm : Form
{
public static event ColourSettingChangedDelegate ColourSettingsChangedEvent;
public delegate void ColourSettingChangedDelegate(Color color);
List<string> adreses;
List<string> bookmarki;
void SelectColour()
{
using (ColorForm colourForm = new ColorForm())
{
if (colourForm.ShowDialog() == DialogResult.OK)
{
//Update colour setting and fire event
OnColourSettingsChanged(colourForm.SelectedColor);
}
}
}
public SettingsForm(List<string> adr, List<string> s)
{
InitializeComponent();
adreses = adr;
bookmarki = s;
}
private void Historyb_Click(object sender, EventArgs e)
{
foreach (Form form in Application.OpenForms)
{
if (form.GetType() == typeof(HistoryForm))
{
form.Activate();
return;
}
}
HistoryForm hf1 = new HistoryForm(adreses);
hf1.Show();
}
private void Bookmarksb_Click(object sender, EventArgs e)
{
BookmarksForm booklist = new BookmarksForm();
booklist.SetAllBookmarks(bookmarki);
booklist.ShowDialog();
}
private void Colorb_Click(object sender, EventArgs e)
{
SelectColour();
}
private void OnColourSettingsChanged(Color color)
{
if (ColourSettingsChangedEvent != null)
ColourSettingsChangedEvent(color);
}
}
Code from ColorForm:
public partial class ColorForm : Form
{
public ColorForm()
{
InitializeComponent();
}
private void Panelcolor_Click(object sender, EventArgs e)
{
ColorDialog colorDlg = new ColorDialog();
colorDlg.AllowFullOpen = true;
colorDlg.AnyColor = true;
if (colorDlg.ShowDialog() == DialogResult.OK)
{
upperpanel.BackColor = colorDlg.Color;
}
}
}
Thank you!
Perhaps it would be better to fire a global event when the settings change, or the particular form colour setting changes, and listen for that event on the form where you need to take action.
for example see this pseudo code:
ColourForm:
Form used just to pick a colour, and store the result in a property.
class ColourForm
{
public Color SelectedColor {get;set;}
private void Panelcolor_Click(object sender, EventArgs e)
{
ColorDialog colorDlg = new ColorDialog();
colorDlg.AllowFullOpen = true;
colorDlg.AnyColor = true;
if (colorDlg.ShowDialog() == DialogResult.OK)
{
this.SelectedColor = colorDlg.Color;
}
}
void Cancel()
{
this.DialogResult = DialogResult.Cancel;
this.Close();
}
void Save()
{
this.DialogResult = DialogResult.OK;
this.Close();
}
}
SettingsForm:
The main form for updating settings, this creates a colour picker form and saved the settings and fires an event if the dialog result of the colour form is an 'ok' result.
class SettingsForm
{
public static event ColourSettingChangedDelegate ColourSettingsChangedEvent;
public delegate void ColourSettingChangedDelegate(Color color);
void SelectColour()
{
using (ColourForm colourForm = new ColourForm())
{
if (colourForm.ShowDialog() == DialogResult.OK)
{
//Update colour setting and fire event
OnColourSettingsChanged(colourForm.SelectedColour);
}
}
}
private void OnColourSettingsChanged(Color color)
{
if (ColourSettingsChangedEvent!=null)
ColourSettingsChangedEvent(color);
}
}
On you Main Form:
The Main form listens for a settings / colour changed event and changes the panel colour to the colour specified in the event when it fires.
class MainForm()
{
//Constructor
MainForm()
{
SettingsForm.ColourSettingsChangedEvent += ColourSettingsChanged;
}
void ColourSettingsChanged(Color color)
{
upperpanel.BackColor = color;
}
}
it would be better to have some kind of settings manager class than have the event on the settings form itself but you should get the idea
I have form1, form2 and a class. i want to use form2 to modify a variable in a class then read that variable in form1.
The thing is that the variable doesn't change when i try to read it from form1, nor it stays after i open form2 again.
This is my code:
Form1
namespace app1 {
public partial class Form1 : Form {
Class1 md = new Class1();
public Form1() {
InitializeComponent();
}
private void loginToolStripMenuItem_Click(object sender, EventArgs e) {
Login login = new Login();
login.MdiParent = this;
login.enbctrs += new ShowFrm(enablecrts);
login.disctrs += new ShowFrm(disablecrts);
login.Show();
}
private void Form1_Load(object sender, EventArgs e) {
if (md.user == null) {
disablecrts();
stat_usr.Text = "No active user";
} else {
stat_usr.Text = md.user.ToString();
}
}
void disablecrts() {
stat_usr.Text = "No active user";
}
void enablecrts() {
stat_usr.Text = md.user;
}
}}
Form2
namespace app1.Forms {
public delegate void ShowFrm();
public partial class Login : Form {
public event ShowFrm enbctrs;
public event ShowFrm disctrs;
int ing_counter = 0;
Class1 md = new Class1();
public Login() {
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e) {
string u = "user";
string p = "pass";
if(Txt_user.Text == u && Txt_pass.Text == p) {
string msg = "Welcome: " + u + "";
MessageBox.Show(msg, "", MessageBoxButtons.OK);
md.changeusr(u);
active_user.Text = md.user.ToString();
enbctrs();
}
private void Login_Load(object sender, EventArgs e) {
if (md.user == null) {
active_user.Text = "No active user";
} else {
active_user.Text = md.user.ToString();
}
}
}}
Class1
namespace app1.Modules {
class Class1 {
public string user;
public void changeusr(string u) {
user = u;
return;
}
}}
There are a number of things that could be improved in your code. But the main issue is that when you create the Login class in your loginToolStripMenuItem_Click() method, that new Login instance is also creating a new instance of Class1 and using that instead of the instance that your Form1 knows about. So when Login changes the user value, it's changing it in a location that Form1 doesn't know anything about.
The simplest fix IMHO is to have Form1 just pass the Class1 reference to Login for it to use, instead of having Login create its own instance. For example:
public partial class Login : Form {
// ...
readonly Class1 md;
public Login(Class1 md) {
InitializeComponent();
this.md = md;
}
// ...
}
And in Form1:
private void loginToolStripMenuItem_Click(object sender, EventArgs e) {
Login login = new Login(md);
login.MdiParent = this;
login.enbctrs += new ShowFrm(enablecrts);
login.disctrs += new ShowFrm(disablecrts);
login.Show();
}
Then when Login changes the user and raises the event, it will have changed the value in the same instance Form1 is using, and so Form1 will get the desired value in its own code.
public static class global{
public static int myInt = 0;
}
public class Form1{
global.myInt = 10;
}
public class Form2{
Console.WriteLine(global.myInt.ToString());
}
trying to get data from the main form to form 2. The main form has a textbox
and a button. when the button is pressed it opens form 2 which will display the data entered in the main form as a series of text blocks.
However I cant get the data to transfer between the forms. the code is bellow.
can anyone help or suggest anything I can do differently?
WPF 1 main form:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void btnOpenForm_Click(object sender, RoutedEventArgs e)
{
//btnset: Takes the values contained in the text boxes and updates
//the student class
//properties.
Student.sFname = firstname.Text;
Student.sSname = secondname.Text;
Window1 details = new Window1();
details.Show();
}
WPF 2 code:
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
private void details_Load(object sender, EventArgs e)
{
Fname.Text = Student.sFname;
Sname.Text = Student.sSname;
}
private void Close_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
}
There are a number of ways to "pass data" between 2 classes. The easiest way is to expose property or method on Window1 and just set the text you need passed. Another way is to create a constructor on Window1 that takes in the data as parameters. Here is code that demonstrates these approaches.
public class Program
{
public static void Main(string[] args)
{
var c1 = new Class1();
c1.DoStuff();
}
}
public class Class1
{
public void DoStuff()
{
var c = new Class2("stuff");
var c2 = new Class2();
c2.AcceptStuff("stuff2");
c.Print();
c2.Print();
c2.MyData = "stuff3";
c2.Print();
}
}
public class Class2
{
private string _myData;
public Class2()
{
}
public Class2(string myData)
{
_myData = myData;
}
public string MyData
{
set { _myData = value;}
}
public void AcceptStuff(string myData)
{
_myData = myData;
}
public void Print()
{
Console.WriteLine(_myData);
}
}
Prints
stuff
stuff2
stuff3
I assume you have a class in MainWindow like:
`Public class Student
{
public static string sFname;
public static string sSname;
}`
When you click open button you are assigning values to those variable, but if you want to access them in another window mention the window name and then class name.
Check this code if its working?
`public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
private void details_Load(object sender, EventArgs e)
{
Fname.Text = MainWindow.Student.sFname;
Sname.Text = Mainwindow.Student.sSname;
}
private void Close_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
}`
I have to send the value of 2 TextBoxes from FormB when I clic on the "validate buton" to the datagridView in FormA;this is what I try to code:
FormB:
namespace RibbonDemo.Fichier
{
public partial class NvFamillImmo : Form
{
public event BetweenFormEventHandler BetweenForm;
SqlDataAdapter dr;
DataSet ds = new DataSet();
string req;
public NvFamillImmo()
{
InitializeComponent();
affich();
}
private void button2_Click(object sender, EventArgs e) //the validate buton
{
if (BetweenForm != null)
BetweenForm(textBox1.Text, textBox2.Text);
}
private void fillByToolStripButton_Click(object sender, EventArgs e)
{
try
{
this.amortissementFiscalTableAdapter.FillBy(this.mainDataSet.amortissementFiscal);
}
catch (System.Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.Message);
}
}
}
}
and this is FormA:
namespace RibbonDemo.Fichier
{
public delegate void BetweenFormEventHandler(string txtbox1value, string txtbox2value);
public partial class FammileImm : Form
{
private NvFamillImmo nvFamillImmo;
public FammileImm()
{
InitializeComponent();
}
private void button2_Click(object sender, EventArgs e)
{
NvFamillImmo frm2 = new NvFamillImmo();
frm2.BetweenForm += frm2_BetweenForm;
frm2.ShowDialog();
}
void frm2_BetweenForm(string txtbox1value, string txtbox2value)
{
//dataGridView1.Refresh();
String str1 = nvFamillImmo.textBox1.Text.ToString();
this.dataGridView1.Rows[0].Cells[0].Value = str1;
}
}
}
EDIT:I filled the method frm2_BetwwenForm but now I get a problem in reference
thanks for Help
No Need to create event for that. you can create properties in second form where you want to send value from existing form. for example if you have two forms FormA and FormB then FormB should contains properties like Value1 and Value2.
//FormB
public class FormB :Form
{
public string Value1{get; set;}
public string Value2{get; set;}
}
Now you can assign value into both properties from FormA.
//FormA
public void button1_click(object sender, EventArgs e)
{
FormB myForm = new FormB();
myForm.Value1 = textBox1.Text;
myForm.Value2 = textBox1.Text;
myForm.Show();
}
Then you can get both textboxes value into FormB. You can handle value into Form Load event
//FormB
public void FormB_Load(object sender, EventArgs e)
{
string fromTextBox1 = this.Value1;
string formTextBox2 = this.Value2;
}
If the FormB is already loaded and want to send value from FormA then create a method UpdateValues() and modify the properties to call that method.
//FormB
string _value1 = string.Empty;
public string Value1
{
get { return _value1; }
set {
_value1 = value;
UpdateValues();
}
}
string _value2 = string.Empty;
public string Value1
{
get { return _value2; }
set {
_value2 = value;
UpdateValues();
}
}
private void UpdateValues()
{
string fromTextBox1 = this.Value1;
string fromTextBox2 = this.Value2;
}
and Assign the values in FormB.Value1 and FormB.Value2 properties from FormA.
//FormA
FormB myForm = new FormB();
public void button1_click(object sender, EventArgs e)
{
if (myForm != null && myForm.IsDisposed == false)
{
myForm.Value1 = textBox1.Text;
myForm.Value2 = textBox1.Text;
}
}
When the value is updated from FormA then UpdateValues() method will be called.