C# : Using statement and this keyword - c#

While wanting to use using statement, I came across a scenario that I don't understand :
private void RoomMealHistory_Click(object sender, EventArgs e)
{
MealRoomPlanning fMealRoomPlanning = new MealRoomPlanning(true);
fMealRoomPlanning .MdiParent = this;
fMealRoomPlanning.Show();
}
This code works correctly and my window is a MdiChild.
However, the following code does not work :
private void RoomMealHistory_Click(object sender, EventArgs e)
{
using (MealRoomPlanning fMealRoomPlanning = new MealRoomPlanning(true))
{
MdiParent = this;
fMealRoomPlanning.Show();
}
}
ArgumentException: 'A form cannot be an MDI child and an MDI parent at the same time.
I also tried to replace this with this.ParentForm doesn't work anymore.
Is there a problem with the scope of this?

In your first snippet, you set the MdiParent-Property of fMealRoomPlanning.
In your second snippet, you set MdiParent of your own class instance (this.MdiParent).
You should set it on the object you are using:
private void RoomMealHistory_Click(object sender, EventArgs e)
{
using (MealRoomPlanning fMealRoomPlanning = new MealRoomPlanning(true))
{
fMealRoomPlanning.MdiParent = this;
fMealRoomPlanning.Show();
}
}
That's why many style-checks recommend using the this-Qualifier although it is redundant. This makes it more clear if you set a local, global or class variable.

Finally I have just understood that Using is not necessary for non-modal Form.
When a non modal form is closed, the Dispose will automatically be called by WinForms.
Unlike Forms opened with ShowDialog for which the Dispose is not called automatically.

Try changing MdiParent = this to fMealRoomPlanning.MdiParent = this

Try Changing the 2nd Code, After creating object for MealRoomPlanning class
change MdiParent = this; to fMealRoomPlanning.MdiParent = this;
private void RoomMealHistory_Click(object sender, EventArgs e)
{
using (MealRoomPlanning fMealRoomPlanning = new MealRoomPlanning(true))
{
fMealRoomPlanning.MdiParent = this;
fMealRoomPlanning.Show();
}
}

Related

C# .NET Substitutes for UserControl Panels

I'm fairly new to GUI-development in C# .NET, using WinForms, and I'm creating an application with one form, (like a main menu), and with different "sub-menus", that can all be opened in the same form. This is what I currently have:
Application with UserPanel1 open.
Application without any UserPanel selected.
I've seen some shady youtuber use UserControls for this, and that's what I'm currently working with. I'm using a TableLayoutPanel, with the UserControls dropped into it.
But I have some problems with this. First, I don't know if this is the correct way to use UserControls and if this will throw any errors.
Second of all, I don't know the exact way to use multiple UserControls in one form, because I can't drag multiple UserControls in a single cell of a TableLayoutPanel, and if I instantiate a new UserControl using some simple code, it won't display all of the custom controls I previously placed (in that UserControl). Here is that code:
private void button1_Click(object sender, EventArgs e)
{
Form1_UserControl1 form1_UserControl1 = new Form1_UserControl1();
form1_UserControl1.Show();
form1_UserControl1.BringToFront();
form1_UserControl1.Dock = DockStyle.Fill;
}
I know that this is probably a simple thing that I'm doing wrong, but I only need some simple advice.
Am I using the right control, or is there a better/easier way to achieve what I'm looking for?
Initialize all UserControls to private fields
TableLayoutPanel add all these UserControls
Use buttons to hide/show them.
My sample code:
public partial class Form1 : Form
{
private UserControl[] myUserControls = new UserControl[3];
public Form1()
{
InitializeComponent();
InitializeUserControls();
}
private void InitializeUserControls()
{
for (int i = 0; i < myUserControls.Length; ++i)
{
myUserControls[i] = new UserControl();
myUserControls[i].Hide();
myUserControls[i].BringToFront();
myUserControls[i].BackColor = Color.Blue;
myUserControls[i].Dock = DockStyle.Fill;
tableLayoutPanel2.Controls.Add(myUserControls[i]);
}
}
private void button1_Click(object sender, EventArgs e)
{
myUserControls[0].Visible = !myUserControls[0].Visible;
}
private void button2_Click(object sender, EventArgs e)
{
myUserControls[1].Visible = !myUserControls[1].Visible;
}
private void button3_Click(object sender, EventArgs e)
{
myUserControls[2].Visible = !myUserControls[2].Visible;
}
}

Pass parameter in an already opened form in C#

I want to pass a parameter to the textbox. I have the following code and it is passing the parameter but not the way I want.
My main form in already open and I want to pass the parameter from my search form. when I do with the code below it opens mt 1 more main form and the parameter is shown in there. I want to by able to show in the opened main form.
When I erase frmMain.Show(); nothing happens.
Main frmMain = new Main();
artikal = "TEST TEST";
frmMain.ed_artiakal.Text = artikal;
frmMain.Show();
any suggestions?
You have many variants to solve your problem.
Option 1
Define and use custom event.
Search form code:
public event EventHandler ArtikalTextChanged;
private void textBox1_TextChanged(object sender, EventArgs e)
{
if (ArtikalTextChanged != null)
ArtikalTextChanged(this, EventArgs.Empty);
}
Main form code:
private void button1_Click(object sender, EventArgs e)
{
Search search = new Search();
search.ArtikalTextChanged += OnArtikalTextChanged;
search.Show();
}
private void OnArtikalTextChanged(object sender, EventArgs e)
{
this.ed_artiakal.Text = (sender as Search).textBox1.Text;
}
Don't forget to make textBox1 of Search form public.
Option 2
Get instance of your main form in search form:
Search form code:
private void textBox1_TextChanged(object sender, EventArgs e)
{
var mainForm = Application.OpenForms.OfType<Main>().FirstOrDefault();
mainForm.ed_artiakal.Text = textBox1.Text;
}
Main form code:
private void button1_Click(object sender, EventArgs e)
{
Search search = new Search();
search.Show();
}
Don't forget to make ed_artiakal control public in your Main form.
Option 3
Share data between forms (recommend)
But if you application is large and you want to make it scaleable and flexible I recommend you to use data-binding technique to share data between forms without coupling them. You can read more at articles: http://msdn.microsoft.com/en-us/library/h974h4y2(v=vs.90).aspx
I have solved my problem in the following way.
On my Search Form I created a public string and when I showed the form I referenced to that string in my case GetItemCode.
The key here was to use ShowDialog() and not to use Show().
SEARCH FORM
Search frmSearch = new Search();
frmSearch.ShowDialog();
ed_artiakal.Text = frmSearch.GetItemCode;
MAIN FORM
public string GetItemCode
{
get { return Artikal; }
}
Now when I close the search form the value is shown in the TextBox on my main form.
Thanks for your answers and comments!

Cannot access a disposed object C# (showdialog dispose)

I am new to c# and kind of winging it. using Microsoft Visual C# 2010
I have checked many similar posts and none of the suggestions seem to help
I am getting the following error: "Cannot access a disposed object"
which references the main form here
private void btn_RunPkgs_Click(object sender, EventArgs e)
{
RunPackages rp = new RunPackages();
this.Hide();
rp.ShowDialog();//The error points to this line
this.Show();
}
here is the code that blows up when the security check fails.
private void securityCheck()
{
if (MyGlobals.FormCheck("RUN_JOBS") == 1)
{
InitializeComponent();
}
else
{
//this.BeginInvoke(new MethodInvoker(this.Close));
//this.DialogResult = System.Windows.Forms.DialogResult.Cancel;
MessageBox.Show("You do not have permission to access this form!");
//this.Close();
this.Dispose();
}
}
EDIT
It looks like I am going to go with Adriano Repetti's idea of putting the security where I call the page, but I am a little nervous now having any security on the page.
private void btn_RunPkgs_Click(object sender, EventArgs e)
{
if (MyGlobals.FormCheck("RUN_JOBS") == 1)
{
RunPackages rp = new RunPackages();
this.Hide();
rp.ShowDialog();
this.Show();
}
else
{
MessageBox.Show("Not for You!");
}
}
private void btn_ListUpdater_Click(object sender, EventArgs e)
{
if (MyGlobals.FormCheck("MDM") == 1)
{
ListUpdater lu = new ListUpdater();
this.Hide();
lu.ShowDialog();
this.Show();
}
else
{
MessageBox.Show("Private!");
}
}
EDIT2
Came up with the following possible solution but am nervous to use it because I am new at this and don't know what issues there might be. Any problems with just creating an event handler for form load?
namespace RunPackages
{
public partial class ListUpdater : Form
{
public ListUpdater()
{
InitializeComponent();
this.Load += new EventHandler(securityCheck);
}
private void securityCheck(object sender, EventArgs e)
{
if (MyGlobals.FormCheck("MDM1") == 0)
{
MessageBox.Show("Not Allowed!");
this.Close();
}
}
You can't dispose of the form within the form itself. The ShowDialog() method tries to access the form on exit for things such as DialogResult.
After a form has been disposed almost all of its methods can't be accessed (and most of its properties are invalid).
In your first line of btn_RunPkgs_Click() you create an object and you dispose it inside its constructor. Per se, even if pretty bad habit you may even call Dispose() from within constructor, it may even work but then you try to use such object ShowDialog() will generate ObjectDisposedException. Note that this code will also lead to same result (an exception):
RunPackages rp = new RunPackages();
rp.Dispose();
Yes you may check IsDisposed but that won't make code readable and problem (IMO) is you're mixing things. Constructor shouldn't contain such logic.
The point isn't just where you dispose your form. What's better is to don't even create such form (let me assume, because you call InitializeComponent(), that securityCheck() is called inside form constructor), for this you may use a factory static method:
public static bool TryShowDialog(Form currentForm)
{
if (MyGlobals.FormCheck("RUN_JOBS") != 1)
return false;
if (currentForm != null)
currentForm.Hide();
RunPackages dlg = new RunPackages();
dlg.ShowDialog();
if (currentForm != null)
currentForm.Show();
return true;
}
Your calling function will then be reduced to:
private void btn_RunPkgs_Click(object sender, EventArgs e)
{
RunPackages.TryShowDialog(this);
}
Note that such function is highly eligible for some refactoring (for example to extract code to hide/show existing form). Something like this:
public static bool ShowDialog<T>(Form currentForm, string authorizationId)
where T : Form, new()
{
if (MyGlobals.FormCheck(authorizationId) != 1)
return false;
if (currentForm != null)
currentForm.Hide();
T dlg = new T();
T.ShowDialog();
if (currentForm != null)
currentForm.Show();
return true;
}
Used like this (now code is reused everywhere):
SecurityHelpers.ShowDialog<RunPackages>(this, "RUN_JOBS");
Please note that calling code may be simplified (authorizationId may be an attribute on RunPackages, for example, and also currentForm can be deduced from current active form).
EDIT Calling Close() isn't better, if window handle has not been created (let's simplify little bit: it's created when window is shown) internally it'll call Dispose() (then above applies).
I would not try to disrupt the chaining of events that lead to the form creation.
The side effects are difficult to predict and what works today could not work in future versions.
Instead I would try a different approach
private void securityCheck()
{
if (MyGlobals.FormCheck("RUN_JOBS") == 1)
{
InitializeComponent();
}
else
{
Label message = new Label();
message.Dock = DockStile.Fill;
message.Text("You do not have permission to access this form!.");
message.TextAlign = ContentAlignment.MiddleCenter;
this.Controls.Add(message);
}
}
In this way I let the form show with just one label that covers the entire form surface with your message. The user could only close the form (provided that you have not removed the Control Box)
By the way, this has the advantage of avoiding dangerous oversights because it doesn't require any change on the calling code and the final effect is to effectively block the use of the form.
If you insist in closing the form during its constructor phase then you could get some advices from this question
I came up with the following, can anyone tell me if there are any issues with this?
namespace RunPackages
{
public partial class ListUpdater : Form
{
public ListUpdater()
{
InitializeComponent();
this.Load += new EventHandler(securityCheck);
}
private void securityCheck(object sender, EventArgs e)
{
if (MyGlobals.FormCheck("MDM1") == 0)
{
MessageBox.Show("Not allowed!");
this.Close();
}
}
etc...
Use a flag. For example change the code, like this:
public bool IsDisposed;
private void securityCheck()
{
if (MyGlobals.FormCheck("RUN_JOBS") == 1)
{
InitializeComponent();
}
else
{
//this.BeginInvoke(new MethodInvoker(this.Close));
//this.DialogResult = System.Windows.Forms.DialogResult.Cancel;
MessageBox.Show("You do not have permission to access this form!");
//this.Close();
this.Dispose();
this.IsDisposed = true;
}
}
Then:
private void btn_RunPkgs_Click(object sender, EventArgs e)
{
RunPackages rp = new RunPackages();
if(rp.IsDisposed)
return;
this.Hide();
rp.ShowDialog();//The error points to this line
this.Show();
}

Form.Show(): Cannot access a disposed object

I have been stuck with this for some time now. I can't open a new form on button click.
If i create and .Show() form in the start form constructor i will work. I dont get it! :-(
StartUp Form
public Form1()
{
InitializeComponent();
startmessage();
br = Logic.loadXML("theshiiiiiittt.xml");
br2 = br.Clone();
loadboxes();
//serializeTest();
t = new Thread(contactDBUpdate);
//t.IsBackground = true;
t.Start();
}
Button event:
private void resultButton_Click(object sender, EventArgs e)
{
ResultForm rf = new ResultForm(this);
rf.Show();
this.Enabled = false;
}
Hope this is enough.
In my case it was caused by the fact that i wanted to make my forms non-modal. So i changed them from form.ShowDialog(parentForm) to form.Show().
But that caused the ObjectDisposedException if i try to show a form a second time because somewhere in the code was this.Close();. Form.Close also disposes it.
MSDN:
When a form is closed, all resources created within the object are
closed and the form is disposed.
I just needed to change
this.Close();
to
this.Hide();
Found my code problem.
I took one more look at the Stack trace and found i a message "Icon".
this.Icon.Dispose();
Startupform had this line.
This code fixed my problem:
private void resultButton_Click(object sender, EventArgs e)
{
ResultForm rf = new ResultForm(this);
rf.Icon = this.Icon;
rf.Show();
this.Enabled = false;
}
Thanks for the helping hands...
The problem is that your form object loose the scope and is disposed off.
If you want to keep the dialog open, use Form.ShowDialog();
Try this:
private void resultButton_Click(object sender, EventArgs e)
{
using(ResultForm rf = new ResultForm(this))
{
rf.ShowDialog();
}
this.Enabled = false;
}
Wile Implementing singleton pattern on windows form I got this error too.
The solution is that you have to assign a null value to the static reference in
protected override void Dispose(bool disposing)
by putting simple line.
obj=null; //obj is the static reference in the class.

Accessing GUI from event handler

When a byte from the serial port is received, it enters this handler correctly, but my label on the GUI does not change. Edit: Yes, it is in the same class as the GUI
Edit 2 The function declaration does not need to be 'static'...I merely copy-pasted an example from msdn
edit 3 It works after getting rid of the static decleration and using something like this.
Thanks for your help
private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
Form1 gui = new Form1(); //main GUI
try
{
SerialPort sp = (SerialPort)sender;
string indata = sp.ReadExisting();
//gui.rxLabel.Text = indata;
gui.txLabel.Text = "testttingg";
}
.......
Why are you declaring a new instance of your form? Just use your form's txLabel
In c#:
this.txLabel.Text = "testing";
In vb.net:
Me.txLabel.Text = "testing"
In the sample code you posted you are creating a new instance / reference to your actual form. Use the existing instance, in addition, use this rather then a new instance.
I had to edit my question as I noticed you were using a static method.
Try this:
public static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
Form1 f = (Form1) sender;
f.textBox1.Text = "testing";
}
private void button1_Click(object sender, EventArgs e)
{
DataReceivedHandler(this, null);
}
Of course I am just calling DataReceivedHandler() from a button event, you can call it from your own event. Point being is you need to pass the current instance, this to the function. Once inside the function do not create a new instance of the form, just set a reference to the current form and use that reference to apply the settings to the property (txtBox or Label or whatever).
It appears you're instantiating a new instance of Form1, instead of accessing the existing form in memory.

Categories

Resources