c# constructor issues (object is null) - c#

i been trying to link constructors but i been having issues as i have a lot of different classes witch share a lot of info with each other as so as it stands currently this is what i want to do
get one of the classes to reverence form1 so i can run a certain method
so this is what i have tryied so far
gscadding.cs
public SoundAlis sounds;
public addingweapons dlc3gsc;
public Form1 elfgsc;
public gscadding elfy;
private gscadding elfy1;
public gscadding(addingweapons dlc3)
{
dlc3gsc = dlc3;
}
public gscadding(gscadding elfy1)
{
// TODO: Complete member initialization
this.elfy1 = elfy1;
}
this is the class i want to get into form one to use a function i made in form 1
this is what i have in form1
elfenlied_program_settings elf;
addingweapons elf_weap;
Parser elfenliedl;
gscadding elfy;
//Parser parser = new Parser("model1887_sp");
public Form1()
{
InitializeComponent();
updater1.CheckForUpdates();
listBoxAdv1.Visible = false;
elf = new elfenlied_program_settings(listBoxAdv1,elfenliedl);
elf_weap = new addingweapons(richTextBoxEx1);
elfenliedl = new Parser("model1887_sp");
elfy = new gscadding(elfy);
timer1.Start();
elf.buttonX2 = buttonX2;
elf.elfenform = this;
// elfe.elfgsc = this;
buttonX2.Visible = false;
buttonX3.Enabled = true;
textBoxX6.Enabled = false;
elfenliedl.buttonX1 = buttonX1;
basicly what im trying to do is form gscadding.cs to call a function called updatesettings();
witch when the form loads and i select a path it updates all string = paths
but i keep getting the

elfgsc is null you have to set it.
public gscadding(addingweapons dlc3, Form1 form)
{
dlc3gsc = dlc3;
elfgsc = form;
}
In your form constructor
elfy = new gscadding(elfy, this);
Now you can call methods in your form from your gscadding class like so:
elfgsc.updatesettings();
As to your second error, passing elfy to itself is useless. Remove elfy and replace with elfy_weap

Related

Return a button object by its name in C# WinForm

I’m developing an application in C# which works with several forms and I would like to implement a method to set the properties of these forms. For each one of these forms, two buttons named “okBtn” and “cancelBtn” were created through Designer. I would like to set the form AcceptButton property as “okBtn” and the form CancelButton property as ”cancelBtn”, but I don’t know how to return the buttons objects by their names. Follow a sample that what I’m trying to do:
static public void SetDialogAppearance(Form form)
{
form.FormBorderStyle = FormBorderStyle.FixedDialog;
form.Icon = PresentationLayer.Properties.Resources.embraer;
form.MinimizeBox = false;
form.MaximizeBox = false;
form.AcceptButton = form.Controls["okBtn"]; //this returns an error
form.CancelButton = form.Controls["cancelBtn"]; //this returns an error
}
I managed to solve this issue doing this:
I created a class that inherit the Form class and with the buttons declared as public fields:
public class OkCancelForm : Form
{
public IButtonControl AcceptBtn { get; set; }
public IButtonControl CancelBtn { get; set; }
}
In the forms, this class is inherited and in the constructor the form buttons are assigned to the fields:
public partial class MyForm : OkCancelForm
{
public MyForm()
{
InitializeComponent();
AcceptBtn = this.okBtn;
CancelBtn = this.cancelBtn;
}
Finally, I used these fields in the SetDialogAppearance class:
static public void SetDialogAppearance(OkCancelForm form)
{
form.FormBorderStyle = FormBorderStyle.FixedDialog;
form.Icon = PresentationLayer.Properties.Resources.embraer;
form.MinimizeBox = false;
form.MaximizeBox = false;
form.AcceptButton = form.AcceptBtn;
form.CancelButton = form.CancelBtn;
form.KeyPreview = true;
}
I don’t know if it’s the best solution (neither the most elegant) but it does work. If someone has a better suggestion I’d really appreciate to know.

Changing form control from user control

I'm trying to changing a user control informations (labels, pictures etc.) from auto added user control. But i cant do it.
Here's my code;
private void KitapButton_Click(object sender, EventArgs e)
{
BıtıkForm BForm = new BıtıkForm();
BForm.kitapGoruntuleme.Visible = true;
}
public partial class BıtıkForm : Form
{
//create controls public instance
public Label label;
public BıtıkForm()
{
InitializeComponent();
//initialize the control
label = new Label();
}
}
Now you can access it from other place like;
BıtıkForm BForm = new BıtıkForm();
BForm.label.Visible = true;
/////// But my Suggestion do not do it like that instead do it like below ///////
BıtıkForm BForm = new BıtıkForm(controlVisible);//Pass the bool value as parameter to the constructor of form
BForm.Show();
And then in form
public partial class BıtıkForm : Form
{
public BıtıkForm(bool controlVisible)
{
InitializeComponent();
//Set Control Visibility
someControl.Visible = controlVisible;
}
}
I didn't use C# too much but It's eventually object oriented. The mistake I made is; I was creating a new instance of 'BıtıkForm' everytime event fired. It could be solved by adding new property where event belongs, and property will carry 'BıtıkForm' object. So It can be managed trough all over the program.

Re-using same method in multiple windows forms

I would like to ask for your help. Will you help captain newbie once again? :)
I have several windows forms where I use datagridview. I would like to format the datagridviews in the same way on all the forms (e.g. AllowUserToAddRows = false;).
To do this I created a class MYFormatting and method as below. I am going to use composition to re-use this method on multiple forms. I would be grateful if you could let tell me if my approach is correct?
public class MyFormating
{
public void FormatDGV(DataGridView dgv)
{
dgv.AllowUserToAddRows = false;
dgv.AllowUserToDeleteRows = false;
dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
dgv.ColumnHeadersVisible = false;
dgv.RowHeadersVisible = false;
dgv.MultiSelect = false;
}
}
When initializing new form
Form1 frmForm1 = new Form1(new MyFormating());
Then in each form I am going to call myFormat method and pass datagridview.
public partial class Form1 : Form
{
private readonly MyFormating _myFormat;
public Managers(MyFormating myFormat)
{
InitializeComponent();
_myFormat = myFormat;
_myFormat.FormatDGV(dgvManagers);
Leaving MyFormatting class as it is and then changing my Form1 code to below would give me same result. Is this still composition? Should I do something like this or convention rather say to follow the way I described above?
When initializing new form
Managers frmManagers = new Managers();
Then in each form I am going to create new MyFormatting instance and pass datagridview to it's method
public partial class Form1: Form
{
private readonly MyFormating _myFormat;
public Form1()
{
InitializeComponent();
myFormat = new MyFormating();
myFormat.FormatDGV(dgvManagers);
I understand your purpose. "Extension" is a more practical method;
public static class UIExtensions
{
public static void FormatDGV(this DataGridView dgv)
{
dgv.AllowUserToAddRows = false;
dgv.AllowUserToDeleteRows = false;
dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
dgv.ColumnHeadersVisible = false;
dgv.RowHeadersVisible = false;
dgv.MultiSelect = false;
}
}
and in your form code(onload or constructor);
dgvManagers.FormatDGV();
Look for Extension Methods: https://learn.microsoft.com/tr-tr/dotnet/csharp/programming-guide/classes-and-structs/extension-methods
I suggest you make a new class which inherits from DataGridView. In this class just set the propertys in the constructor as you wish. Rebuild the project and your own DataGridView should show up in the Toolbox. Just place it on the Form like you would do with the standard DataGridView.
Example for the DataGridView with predefined values:
public class MyDataGridView: DataGridView
{
public MyDataGridView()
{
AllowUserToAddRows = false;
AllowUserToDeleteRows = false;
AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
ColumnHeadersVisible = false;
RowHeadersVisible = false;
MultiSelect = false;
}
}
And also a screenshot of the custom DataGridView in Action:

Accessing Form's Controls from another class

I have a windows forms application with some controls added to the designer. When I want to change something (LIKE) enabling a text box from inside the Form1.cs, I simply use:
textBox1.Enabled = true;
but now I have a separated class called class1.cs.
How could I enable textBox1 from a static function class1.cs?
NOTE: I did not try any code because I am totally clueless about doing this.
EDIT: Lot of edit.
public partial class Form1 : Form
{
// Static form. Null if no form created yet.
private static Form1 form = null;
private delegate void EnableDelegate(bool enable);
public Form1()
{
InitializeComponent();
form = this;
}
// Static method, call the non-static version if the form exist.
public static void EnableStaticTextBox(bool enable)
{
if (form != null)
form.EnableTextBox(enable);
}
private void EnableTextBox(bool enable)
{
// If this returns true, it means it was called from an external thread.
if (InvokeRequired)
{
// Create a delegate of this method and let the form run it.
this.Invoke(new EnableDelegate(EnableTextBox), new object[] { enable });
return; // Important
}
// Set textBox
textBox1.Enabled = enable;
}
}
This is just another method:
TextBox t = Application.OpenForms["Form1"].Controls["textBox1"] as TextBox;
You shouldn't really change UI controls in your Form from your class1, but instead create a method or a property in class1 that would tell if the textbox should be enabled or not.
Example:
// I changed the name class1 to MySettings
public class MySettings
{
public bool ShouldTextBoxBeEnabled()
{
// Do some logic here.
return true;
}
// More generic
public static bool SetTextBoxState(TextBox textBox)
{
// Do some logic here.
textBox.Enabled = true;
}
// Or static property (method if you like)
public static StaticShouldTextBoxBeEnabled { get { return true; } }
}
Then in your form:
MySettings settings = new MySettings();
textBox1.Enabled = settings.ShouldTextBoxBeEnabled();
// Or static way
textBox1.Enabled = MySettings.StaticShouldTextBoxBeEnabled;
// Or this way you can send in all textboxes you want to do the logic on.
MySettings.SetTextBoxState(textBox1);
You can pass the instance of your Form to the class
MyForm frm = new MyForm();
MyClass c = new MyClass(frm);
Then your class can take that instance and access the textbox
public class MyClass
{
public MyClass(MyForm f)
{
f.TextBox1.Enabled = false;
}
}
The design does not look OK
It is better to call the class in your form and based on the value returned, manipulate the textbox
//MyForm Class
MyClass c = new MyClass();
c.DoSomethings();
if(c.getResult() == requiredValue)
textBox1.enabled = true;
else
textBox1.enabled = false;
//MyForm Class ends here
UPDATE
public class Class1
{
public static int SomeFunction()
{
int result = 1;
return result;
}
public static void SomeFunction(out int result)
{
result = 1;
}
}
Usage
if(Class1.SomeFunction() == 1)
textBox1.Enabled = true;
else
textBox1.Enabled = false;
OR
int result = 0;
Class1.SomeFunction(out result);
if(result == 1)
textBox1.Enabled = true;
else
textBox1.Enabled = false;
You could let your class1 have an event to enable the Textbox.
public class Class1
{
public event Action<object, EventArgs> subscribe ;
private void raiseEvent()
{
var handler = subscribe ;
if(handler!=null)
{
handler(this,EventArgs.Empty);//Raise the enable event.
}
}
}
Let the class containing the TextBox subscribe to it somehow. In TextBox wrapper class
public class TextBoxWrapper
public void EnablePropertyNotification(object sender, EventArgs args)
{
TextBox1.Enabled = true ; //Enables textbox when event is raised.
}
public TextBoxWrapper()
{
class1Instance.subscribe+=EnablePropertyNotification ;
}
To access/modify a Form Element property, just write this in your outside Class.
Form1.ActiveForm.Controls["textBox1"].Enabled = true;
Where textBox1 is the variable name of TextBox.
What this actually does: Gets the active Form object's control specified by the name in string.
WARNING: Active form means the form which is currently open and focused on. If you do something else on your computer, with your minimized WindowsForm application, the Form1.ActiveForm will not get the form, instead, it will give null, which can lead to errors later. Be careful!
based on the answer from #vr_driver you can do that to avoid problems with other containers like groupbox, panels...
TextBox t = Application.OpenForms["Form1"].Controls.Find("textBox1", true)[0] as TextBox;
In this example you have a form called Main.cs and a class called MyClass:
In MyClass (Note: the name of my Form Class = 'Main'):
Main ui = new Main();
ui.toolStripProgressBarStickers.PerformStep();
In (FormName).Designer.cs so in my case Main.designer.cs change the appropriate control from 'private' to 'public':
public System.Windows.Forms.ToolStripProgressBar toolStripProgressBarStickers;
This solved it for me.
Thanks, Ensai Tankado
I had to do this at work and didn't find that any of these answers matched what I ended up doing, so I'm showing how I made it work.
First, initialize a copy of your class in your load event.
NameOfClass newNameofClass;
Then you want to bind to your class (in the load event):
textBox1.DataBindings.Add(new Binding("Enabled", newNameofClass, "textBox1Enabled"));
In your class, do the following:
private bool textBox1Enabled = false;
public bool TextBox1Enabled
{
get
{
return textBox1Enabled;
}
set
{
textBox1Enabled = value;
}
}
The false setting will initialize your textbox to being disabled
Set textBox1Enabled to true if you want to enable by default.
If you have other logic to enable/disable the textbox, simply modify the value of textBox1Enabled accordingly.
Very easy:
Create an Instance of your Form Object where want to access the Elements from.
Form1 ui = new Form1();
and now change the Form Elements to "public" - like this in the Designer Code:
...
public System.Windows.Forms.TextBox textBox6;
...
Now you can access them like this in your Code:
ui.textBox6 ...
I had the same problem. I used windows forms & Visual Studio to generate a UI in a utility with textbox, checkbox, and button controls but ALL the code was in the same class.
I'm rewriting the utility now that I know "more" OOP concepts and created actual objects and separate classes. I too had problems getting the separate classes to be able to access the form controls and any shared methods that are in the form class. I tried the various suggestions in this thread as well as other threads but none of those solutions worked for me.
What worked for me (not sure if its the right thing to do or not) was I had each class that needed to access the controls and forms methods inherit from the Form.
Here is the relevant part of the Form.cs file:
namespace Utility
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void WriteNote(string noteText, bool asHeading = false)
{
//Writes Messages to the Message box in the UI
Font font1 = new Font(this.ResultsTB.Font, FontStyle.Bold);
Font font2 = new Font(this.ResultsTB.Font, FontStyle.Regular);
if (asHeading)
this.ResultsTB.Font = font1;
else
this.ResultsTB.Font = font2;
this.ResultsTB.AppendText(noteText + "\r\n");
}
My Form contains a textbox called DirTB and a method called "WriteNote" that writes info to another textbox called ResultsTB. Here is the class (at least as far down as the first successful call of the WriteNote method from the Form:
namespace Utility
{
public class AppServerDTO : Form1
{
#region App Server attributes
//attributes listed here
#endregion App Server attributes
#region AppServerDTO Constructor
public AppServerDTO()
{
//These methods verify and set all the attributes
VerifyInstallFolder();
}//end of constructor AppServer
#endregion AppServerDTO Constructor
#region AppServerDTO class methods
public void VerifyInstallFolder()
{
string keypath = string.Empty;
string locationVerification = DirTB.Text + #"\SomeText";
for (int i = 0; i < 4; i++) //allows 3 attempts to get the install folder right
{
if (Directory.Exists(locationVerification))
{
i = 4;//Kills the loop
}
else if (!Directory.Exists(locationVerification))
{
locationVerification = DirTB.Text + #"\SomeMoreText";
}
else if (!Directory.Exists(locationVerification))
{
WriteNote("The directory listed in the Install Directoy box is not reachable.");
WriteNote("Please select the correct directory.");
WriteNote("The correct directory is the folder that contains the ApplicationUpdates & UpdateManager folders.");
WriteNote(#"i.e. C:\Somewhere or D:\Someplace\Somewhere");
var folderpath = FolderPrompt(#"C:\");
DirTB.Text = folderpath; //updates the install folder textbox to the new location
keypath = folderpath;
i++;
}
}//end for loop
}//end VerifyInstallFolder
As long as you are very careful with what you mark as public vs private, it should be ok.
This is how you should do :
I wrote the code below in my form class :
public static Form1 form = null;
private delegate void SetImageDelegate(Image image);
public Form1()
{
InitializeComponent();
form = this;
}
public static void SetStaticImage(Image image)
{
if (form != null)
form.pic1.Image = image;
}
private void setImage(Image img)
{
// If this returns true, it means it was called from an external thread.
if (InvokeRequired)
{
// Create a delegate of this method and let the form run it.
this.Invoke(new SetImageDelegate(setImage), new object[] { img });
return; // Important
}
// Set textBox
pic1.Image = img;
}
and the code below should be in anouther class :
Form1 frm= Form1.form;
frm.pic1.Image = image;
Note that i changed private static Form1 form = null; to public static Form1 form = null;
Good Luck ... Written by Hassan Eskandari :)

C# referencing textbox from another class

new at C# so be nice...
I am trying to send some text to a form textbox using the following code:
SettingsForm.cs
namespace BluMote
{
public partial class SettingsForm : Form
{
public void send2Display(string whatWasSent)
{
this.rtbDisplay.Text = whatWasSent;
}
private void cmdOpen_Click(object sender, EventArgs e)
{
commToy.Parity = "None";
commToy.StopBits = "One";
commToy.DataBits = "8";
commToy.BaudRate = "115000";
commToy.PortName = "COM4";
commToy.OpenPort();
}
.........
}
}
And i am (trying) calling it from another class like so:
namespace PCComm
{
class CommunicationManager
{
#region OpenPort
public bool OpenPort()
{
try
{
if (comPort.IsOpen == true) comPort.Close();
comPort.BaudRate = int.Parse(_baudRate);
comPort.DataBits = int.Parse(_dataBits);
comPort.StopBits = (StopBits)Enum.Parse(typeof(StopBits), _stopBits);
comPort.Parity = (Parity)Enum.Parse(typeof(Parity), _parity);
comPort.PortName = _portName;
comPort.Open();
PCComm.frmMain form = new PCComm.frmMain();
form.send2Display("test");
return true;
}
catch (Exception ex)
{
DisplayData(MessageType.Error, ex.Message);
return false;
}
}
#endregion
}
}
And "test" does not display in the textbox field
But as you can see, its not working... What am i missing?
David
send2Display is a method, you need to call it with a parameter, not assign to it.
BluMote.SettingsForm form = new BluMote.SettingsForm();
form.send2Display("test");
EDIT:
If you are calling the method from inside the SettingsForm class, then you don't need to create a new instance. Try:
this.send2Display("test");
EDIT Based on updated question:
The problem is that the form that you are creating in OpenPort() is not the one that is displayed on screen, so any updates to the textbox won't show on screen. Here are a few quick and dirty ways to remedy this:
Pass a reference to the textbox into your method. I don't recommend this approach, because you will end up with view dependencies in your model.
Return a string from OpenPort() and pass the return value to sendToDisplay.
Define a property LastMessage of type string in CommunicationManager and assign to it in OpenPort(). Then read from it in SettingsForm and pass its value to sendToDisplay.
You have to have an instance of a form object to do that, like this:
BluMote.SettingsForm form = new BluMote.SettingsForm();
form.Show()
form.send2Display("test");
BluMote.SettingsForm.send2display = "test";
Should be:
BluMote.SettingsForm form = new BluMote.SettingsForm();
form.Show();
form.send2Display("test");
But this creates a new instance, probably not what you want. You want to change the text on the currently displayed form, so you need to pass the instance the method needs to act on into the OpenPort method:
namespace PCComm
{
class CommunicationManager
{
#region OpenPort
public bool OpenPort(BluMote.SettingsForm form)
{
try
{
if (comPort.IsOpen == true) comPort.Close();
comPort.BaudRate = int.Parse(_baudRate);
comPort.DataBits = int.Parse(_dataBits);
comPort.StopBits = (StopBits)Enum.Parse(typeof(StopBits), _stopBits);
comPort.Parity = (Parity)Enum.Parse(typeof(Parity), _parity);
comPort.PortName = _portName;
comPort.Open();
//PCComm.frmMain form = new PCComm.frmMain();
form.send2Display("test");
return true;
}
catch (Exception ex)
{
DisplayData(MessageType.Error, ex.Message);
return false;
}
}
#endregion
}
}
Then, somewhere in Form1 (like the load event), you'll want to instantiate the class dependent on it.
CommunicationManager comm = new CommunicationManager();
comm.OpenPort(this);
There are few issues in your code.
Calling a method like a property.
BluMote.SettingsForm.send2display = "test"; // This is wrong
Trying to access SettingsForm class members from another class like accessing static members.
First you have to parse SettingsForm instance to the 'Other Class'.
//In Other Class
private SettingsForm settingsForm;
// Get the instance as a parameter in Constructor (this is one of options)
public OtherClass(SettingsForm instanceOfSettingsForm)
{
settingsForm = instanceOfSettingsForm;
}
//Now you can call send2Display method from OtherClass
settingsForm.send2Display("Test");
You might change the code below and see if it works:
public void send2Display(string whatWasSent)
{
this.rtbDisplay.Text = whatWasSent;
this.rtbDisplay.refresh();
}

Categories