How to use a dynamic button in another class - c#

I want to make a dynamic button and control it.
But I got an error in the line
MainMenuButton(true, Form);
How can I correct it?
Form1.cs
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
UI Teemp;
ClientSize = new Size(Bounds.Width, Bounds.Height-35);
Teemp.MainMenuButton(true, Form);
}
}
and UI.cs
class UI
{
public void MainMenuButton(Boolean Mode, Form Form1)
{
if (Mode == true) //Create
{
System.Windows.Forms.Button StartB = new System.Windows.Forms.Button();
Form1.Controls.Add(StartB);
StartB.Text = "Start";
StartB.Top = 300;
//StartB.Bottom = 100;
StartB.Left = 400;
}
else
{
// this.Controls.Remove(StartB);
}
}
}

You have to create an instance of the UI class first. UI Teemp; only declares a local variable of type UI but does not initializes it with an UI object instance. One cannot use uninitialized local variables.
When declaring the Teemp variable, you can at the same time initialize it with an UI object instance:
UI Teemp = new UI();
There is a second problem with your code. When invoking MainMenuButton, you will need to pass the Form object instance. In your code, Form is a type name and does not refer to an object instance. Use the this keyword:
Teemp.MainMenuButton(true, this);
The this keyword refers to the current instance of the class in which it is being used. With regard to your example, this would refer to the Form1 object instance.
I also want to comment on another thing. Technically not being a problem, but naming your second argument of the MainMenuButton "Form1" can be confusing, since there is also a type named "Form1". With regard to C# it is generally recommended that the first letter in variable and argument names is lowercase, whereas the first letter in type names should be uppercase. Hence the source code for your MainMenuButton method could perhaps look similar like this:
public void MainMenuButton(bool createButton, Form form)
{
if (createButton)
{
System.Windows.Forms.Button startB = new System.Windows.Forms.Button();
form.Controls.Add(startB);
startB.Text = "Start";
startB.Top = 300;
//startB.Bottom = 100;
startB.Left = 400;
}
else
{
// this.Controls.Remove(startB);
}
}
Keeping variable and argument names different from type names avoids confusion when reading and writing code, thus lowering the risk of introducing bugs :)

Related

Passing a variable between forms WINFORMS [duplicate]

Wierd behaviour when passing values to and from second form.
ParameterForm pf = new ParameterForm(testString);
works
ParameterForm pf = new ParameterForm();
pf.testString="test";
doesn't (testString defined as public string)
maybe i'm missing something? Anyway I'd like to make 2nd variant work properly, as for now - it returns null object reference error.
Thanks for help.
Posting more code here:
calling
Button ParametersButton = new Button();
ParametersButton.Click += delegate
{
ParameterForm pf = new ParameterForm(doc.GetElementById(ParametersButton.Tag.ToString()));
pf.ShowDialog(this);
pf.test = "test";
pf.Submit += new ParameterForm.ParameterSubmitResult(pf_Submit);
};
definition and use
public partial class ParameterForm : Form
{
public string test;
public XmlElement node;
public delegate void ParameterSubmitResult(object sender, XmlElement e);
public event ParameterSubmitResult Submit;
public void SubmitButton_Click(object sender, EventArgs e)
{
Submit(this,this.node);
Debug.WriteLine(test);
}
}
result:
Submit - null object reference
test - null object reference
pf.ShowDialog(this); is a blocking call, so pf.Submit += new ParameterForm.ParameterSubmitResult(pf_Submit); is never reached: switch the order.
Submit(this,this.node); throws a null object reference because no event is assigned to it (see above). Generally, you should always check first: if (Submit != null) Submit(this,this.node);
You should change ``pf.ShowDialog(this);topf.Show(this);` so that your main form isn't disabled while your dialog box is open, if that's what you want, or use the model below (typical for dialog boxes.)
I'm not sure what pf_Submit is supposed to do, so this might not be the best way to go about it in your application, but it's how general "Proceed? Yes/No" questions work.
Button ParametersButton = new Button();
ParametersButton.Click += delegate
{
ParameterForm pf = new ParameterForm(testString);
pf.ShowDialog(this); // Blocks until user submits
// Do whatever pf_Submit did here.
};
public partial class ParameterForm : Form
{
public string test; // Generally, encapsulate these
public XmlElement node; // in properties
public void SubmitButton_Click(object sender, EventArgs e)
{
Debug.WriteLine(test);
this.Close(); // Returns from ShowDialog()
}
}
When you want to use your second variant, you have to use a getString()-Method, where you can put the e.g. "testString". The way you wrote it, "testString" should be a method (and got brackets).
EDIT (a bit more precise):
You could write:
pf.getString(testString);
, if "pf" is an instance of your own class, otherwise you had to look up, whether you can retrieve a String in this class.
the thing was in line order :)
pf.Submit += new ParameterForm.ParameterSubmitResult(pf_Submit);
and
pf.Test = "test";
should have been set before
pf.ShowDialog(this);
my mistake thingking that parameter can be passed after 2nd form was displayed
thnx for answers

Static member inside the form

In my project on the WindowsForms, if I have a static instance inside the form, when I'm opening my form at the first time, it works. But if I'll close it and open again, the form will be empty. Why can it be?
public partial class Computer : Form
{
static Indicators indicators = new Code.Indicators();
}
P.S. I'm making it static, because I want to save it's value after the form will be closed.
Edit 1: Opening the form
private void button3_Click(object sender, EventArgs e)
{
Computer computer = new Computer();
computer.ShowDialog();
}
Edit 2: Computer Form
namespace WF
{
public partial class Computer : Form
{
static Code.Indicators indicators = new Code.Indicators();
public Computer()
{
if (indicators.isComputerAlreadyRunning == false)
{
InitializeComponent();
pictureBox1.Image = Properties.Resources.Computer1;
indicators.isComputerAlreadyRunning = true;
}
}
// My not successful try to save the value of the variable
public Code.Indicators ShowForm()
{
return new Code.Indicators(indicators.isComputerAlreadyRunning);
}
}
}
I don't think that static members work well with the Windows Form lifecycle.
I suggest you make Indicators a normal instance member of your form. To preserve state beyond the life of a form you can copy your state from the form and copy it back to the form when you open it.
// Keep this in the proper place
var indicators = new Code.Indicators();
...
// Copy back and forth for the life time of the form
using (var form = new Computer())
{
form.Indicators.AddRange(indicators);
form.Close += (s, e) =>
{
indicators.Clear();
indicators.AddRange(form.Indicators);
}
}
...
According to the constructor in the Computer class, the indicators.isComputerAlreadyRunning is set to true the first time the form is created.
So when Computer is created the second time, the if condition will fail and the whole if block will be skipped. That means your InitializeComponent(); won't get run and hence nothing in the form will shows up.
Put the InitializeComponent(); outside the if clause to make it work.

c# objects modification: a strange behaviour

I'm developing a WPF C# application and I have a strange behaviour in modification of objects. I try to explain it in general way.
Suppose that you have an object of a class described as follows:
public class A
{
int one;
bool two;
List<B> listofBObjects;
}
where B is:
public class B
{
int three;
int four;
}
I pass an instance of A class and an instance of B class from a window to another, only defining two variables of type A and B in the second window and passing them before the Show() method, with the following code, executed into an instance of window FirstWindow:
SecondWindow newWindow = new SecondWindow();
newWindow.instanceOfA = this.instanceOfA; //instanceOfA is of type A
newWindow.instanceOfB = this.instanceOfA.listOfBObjects[0]; //instanceOfB is of type B
newWindow.Show();
If I have to repeat this code twice(that is, opening twice the window), in the first execution everything works as expected, infact if I modify values in instanceOfB variable, I see the modification also in instanceOfA variable. But, in the second execution, the modification in instanceOfB does not affect instanceOfA...
The modifications are done in newWindow. For example:
this.instanceOfB.three++;
this.instanceOfB.four--;
Imagine that you are in the FirstWindow. Click on a button and SecondWindow opens, passing both variables as described above. In SecondWindow, do some modifications, click on OK and SecondWindow closes, returning control to FirstWindow. If I reclick on the same button, I reopen SecondWindow. If I do modifications now, they do not affect both variables.
I try to have a look (in VS2012) at both variables in the console with control expression and I see that, in the first pass of code, both variables changes when code above is executed but, in the second pass of code, only instanceOfB changes...
EDIT:
Following the code that I use to pass parameters to SecondWindow...types are explaind below
IntermediatePosition obj = ((FrameworkElement)sender).DataContext as IntermediatePosition; //IntermediatePosition is Class B
IntermediatePositionsSettingsWindow ips = new IntermediatePositionsSettingsWindow();
ips.currentIntermediatePosition = obj;//this is the instanceOfB
ips.idxOfIpToModify = obj.index;
ips.currentSingleProperty = this.currentPropertyToShow; //this is the instanceOfA object
ips.sideIndex = this.sideIndex;
ips.ShowDialog();
Consider that obj is given by a button selection into a datagrid, in which each row represents an IntermediatePosition object. In the datagrid, there is a column button and, clicking by buttons, IntermediatePositionsSettingsWindow is opened with the proper data
EDIT:
I've performed the folloqing check:
this.currentPropertyToShow.sides[this.sideIndex].intermediatePositionList[i].Ge‌​tHashCode() == obj.GetHashCode()
where i is the index of related IntermediatePosition object. At first usage of IntermediatePositionsSettingsWindow the objects result equals, but in second usage they are different
Why this thing happens?
If it is needed any other clarification, I will edit the question
Thanks
It's difficult to give a proper answer to this, as there is insufficient code to correctly work out the issue. However, if you are databinding, then I believe you need to implement this interface. It is possible that you're issue is simply that you're model is not reflecting the changes to the screen.
I can't reproduce your problem. Here's a simplified representation of your class relation (as I understood from your question). Please let us know if this is correct:
public partial class MainWindow : Window
{
internal A instanceOfA;
internal B instanceOfB;
public MainWindow()
{
InitializeComponent();
instanceOfB = new B() { };
instanceOfA = new A() { listOfBObjects = new List<B>() { instanceOfB } };
}
private void Button_Click(object sender, RoutedEventArgs e)
{
SecondWindow newWindow = new SecondWindow();
newWindow.instanceOfA = this.instanceOfA; //instanceOfA is of type A
newWindow.instanceOfB = this.instanceOfA.listOfBObjects[0]; //instanceOfB is of type B
newWindow.Show();
}
}
public partial class SecondWindow : Window
{
internal A instanceOfA;
internal B instanceOfB;
public SecondWindow()
{
InitializeComponent();
Loaded += SecondWindow_Loaded;
}
void SecondWindow_Loaded(object sender, RoutedEventArgs e)
{
MessageBox
.Show(String.Format("{0}",
this.instanceOfB == this.instanceOfA.listOfBObjects[0]));
this.instanceOfB.three++;
this.instanceOfB.four--;
}
}
Note: this is not an answer, just trying to establish some common ground for further discussions, as comments don't leave you enough freedom for code samples.
Thanks to #pm_2 and #BillZhang comments, I found a row in my code in which this.currentPropertyToShowwas edited. After the returning back at first window, infact, I perform the refresh of the window, but it is not needed to edit this.currentPropertyToShow, so I have commented it and everything works!
Thanks everybody for precious comments and suggestions!

C# - implementation of method which is using generic types

I am creating a MDI form and I have a method that loads the different forms. Now I need to make a little modification - I need to add functionality that calls one child form from within another child form.
Because I need this in several different places I made a new class from who all the classes that need this functionality inherits. I want to make it work with generic types so I can pass every form class that I may need like LoadAForm(MyForm1) or LoadAForm(MyForm2) and so on.. I hope I it's clear what I want as final result.
I tried this:
protected void LoadAForm<T>(ref T sender)
{
MainForm frm = this.MdiParent as MainForm;
T temp;
if (frm != null)
{
sender = SingletonFormProvider.GetInstance<temp>(frm, true);
sender.MdiParent = frm;
sender.Dock = DockStyle.Fill;
sender.Show();
}
}
which doesn't work. But I have almost no experience with generics even more when they are used in methods, so I don't know how to go on.
What I get as an error using this syntax is The type or namespace "temp" could not be found...". I'm not even sure that this is the way to do it.GetInstance<>` has to take an argument of the same type as the type of the form I'm calling.
You need to use the type parameter, not the variable name:
sender = SingletonFormProvider.GetInstance<T>(frm, true);
Also, to ensure that T is valid (as your comment suggests) you will need to constrain it:
protected void LoadAForm<T>(ref T sender) where T : Form
I don't think you need generics here. I think you could easier work by simply using Form as the concrete type:
protected void LoadAForm(ref Form sender)
{
MainForm frm = this.MdiParent as MainForm;
Form temp;
if (frm != null)
{
sender = SingletonFormProvider.GetInstance(frm, true);
sender.MdiParent = frm;
sender.Dock = DockStyle.Fill;
sender.Show();
}
}

C# - using ColorDialog across forms

I have a windows form application. On the main form a user will enter a number of item, etc and then click a button which will open a new form (either a small form or a large form depending on a checkbox). Now on my main application I have a file menu - under which is settings - change background colour. This opens the colordialog. If a user does not pick anything the background colours will stay default. However if they change it on the main entry form i change the background of a few textboxes - code below.
private void warning1ToolStripMenuItem_Click(object sender, EventArgs e)
{
colorDialog1.ShowDialog();
Warn1Color = colorDialog1.Color.ToString();
if (Warn1Color != null)
{
tbWarn1Hrs.BackColor = colorDialog1.Color;
tbWarn1Mins.BackColor = colorDialog1.Color;
tbWarn1Secs.BackColor = colorDialog1.Color;
tbWarn1Msg.BackColor = colorDialog1.Color;
}
}
Now my problem is how to I get this to then change the background in the other form that opens. I was hoping I could pass the string across in the new form constructor as i do with a number of other values.
i.e - here is my code in the new form....(note - string Warn1Color was passed across in constructor and then made = to the string _Warn1Color. If it is null then background will be default yellow but it cant convert type string to system.drawing.color. Does anyone see an easy solution to this or what I could do to get this working easily.
if (_Warn1Color == null)
{
this.BackColor = System.Drawing.Color.Yellow;
}
else
this.BackColor = _Warn1Color;
Pass the Color on via the Constructor not a string. If this is not possibly for whatever reason, you could create a ColorConfigClass that holds the required Color and you can set it when used.
You should create a static class to store your configuration data such as this colour style. You can then set this value once you have prompted the user for the change and you can also call the Color value from any other form when you need to use it.
Your static class should look something like this...
public static class StyleSettings{
private static Color _warn1Color = Color.FromArgb(255, 0, 0);//default colour
public static Color Warn1Color {
get { return _warn1Color; }
set { _warn1Color = value; }
}
}
Then you can use this in your example method like...
private void warning1ToolStripMenuItem_Click(object sender, EventArgs e)
{
if (colorDialog1.ShowDialog() == DialogResult.OK)
{
StyleSettings.Warn1Color = colorDialog1.Color;
tbWarn1Hrs.BackColor = StyleSettings.Warn1Color;
tbWarn1Mins.BackColor = StyleSettings.Warn1Color;
tbWarn1Secs.BackColor = StyleSettings.Warn1Color;
tbWarn1Msg.BackColor = StyleSettings.Warn1Color;
}
}
I assume you used a string because you wanted to be able to pass null, and System.Drawing.Color being a struct can not be null.
In which case either use Nullable ( http://msdn.microsoft.com/en-us/library/b3h38hb0%28v=vs.80%29.aspx ) which can be null or you can consider some other value as "default", say alpha=0.
To pass a value in your constructor simply go to the code file for the form (the one where you code the stuff for the events) and find the constructor function (has the same name as the form) e.g.:
namespace MyApp
{
public partial class MyForm : Form
{
public MyForm()
{
InitializeComponent();
}
...
And add the parameters to it:
namespace MyApp
{
public partial class MyForm : Form
{
public MyForm(System.drawing.color background)
{
InitializeComponent();
...do whatever you want with background...
}
...
Of course you also need to edit the places you create this form, e.g. change
form = new MyForm();
form.Show();
to
form = new MyForm(backgroundColour);
form.Show();

Categories

Resources