Why can't I use a parameter string to name my button? - c#

I'm creating a lot of buttons on the back end so I figured it would be intelligent to abstract it out to cut down on lines of code. When I try to do this though, it gives me an error saying "A local or parameter named "buttonName" cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter". Am I missing something here? I thought this was the exact reason to use a parameter in this situation.
Here is an example of what I'm trying to do.
turn this
Button buttonDetailsEdit = new Button();
buttonDetailsEdit.ID = "ButtonDetailsEdit";
buttonDetailsEdit.Text = "Edit";
buttonDetailsEdit.UseSubmitBehavior = false;
buttonDetailsEdit.Click += new EventHandler(EditCall);
PlaceHolderDetailsContent.Controls.Add(buttonDetailsEdit);
Button buttonDetailsBack = new Button();
buttonDetailsBack.ID = "ButtonDetailsBack";
buttonDetailsBack.Text = "Back to List";
buttonDetailsBack.UseSubmitBehavior = false;
buttonDetailsBack.Click += new EventHandler(IndexCall);
PlaceHolderDetailsContent.Controls.Add(buttonDetailsBack);
Into this (with a method call in place of the old code)
void CreateButton(string buttonName, string buttonIDText, string buttonText, PlaceHolder PlaceHolderName, string methodCall)
{
Button buttonName = new Button();
buttonName.ID = buttonIDText;
buttonName.Text = buttonText;
buttonName.UseSubmitBehavior = false;
buttonName.Click += new EventHandler(methodCall);
PlaceHolderName.Controls.Add(buttonName);
}
the methodCall portion also throws an error here, I'm assuming due to "methodCall" not existing in this instance.

You can't have two variables string buttonName and Button buttonName with the same name in the same scope.
Try to rename your button to, for example, Button newButton

You have declared a parameter named buttonName:
string buttonName
And you have declared a Button variable of the same name:
Button buttonName
You cannot have both. This is what the compiler is complaining about.
Now, actually, your issue seems to be that you want to use the content of the parameter as a local variable name. This is generally not possible - variable names must be known at compile time, not only at runtime.
Luckily, you do not actually need that - it does not matter what your local Button variable is called within your method, as that name will be lost when the method ends (actually, it will probably not even make it through compilation). The important part is that with each invocation of your method, a new Button instance will be created (and ultimately added to the list).
Therefore, simply rename your Button variable to newButton and drop the buttonName parameter because it isn't used any more.

The variable name buttonName was reused and the type of methodCall was incorrect. You need a delegate parameter to allow the selected function to be passed into the method.
void CreateButton(string buttonName,
string buttonIDText,
string buttonText,
PlaceHolder placeHolder,
EventHandler methodCall) // needed to fix your type
{
var button = new Button(); //reused variable name
button.ID = buttonIDText;
button.Name = buttonName; //you missed assigning the button name
button.Text = buttonText;
button.UseSubmitBehavior = false;
button.Click += methodCall; // you dont need to do new EventHandler
placeHolder.Controls.Add(button);
}

Related

The name "locBox does not exist"

I'm using code to create a dynamic text box, including assigning it a name, and then attempting to append new text to the textbox, however I'm receiving an error that the name doesn't exist in the current context.
Am I missing something simple, or have a done something wrong? I apologize if this is a basic thing I'm doing wrong; I'm still learning.
Here's the code in question:
TextBox dynamicTextBox = new TextBox();
dynamicTextBox.Name = "locBox";
dynamicTextBox.Multiline = true;
dynamicTextBox.Width = 300;
dynamicTextBox.Height = 40;
dynamicTextBox.Text = "Text ");
dynamicTextBox.ControlAdded += locBox;
locBox.AppendText = var1.ToString();
locBox.AppendText = var2.ToString();
The locBox is not defined. you have to remove the last two statement. and change the last statement after removal too.
replace "dynamicTextBox" to the form control instance .
{form instance name}.ControlAdded += locBox;
"{}" is a place holder.
I don't know how helpful this is.

Access Gtk# (GtkSharp) Label child of a Button

I have a C# project in MonoDevelop.
Long story short is I found I wasnt able to apply styling/pango/markup/images if I used the Button with Label in the Stetic GUI.
The documentation i read and some code I see said to make a Label or Image and pack it into the Button.
I did that for a Label and it worked successfully to style it.
A sample of the object Build method:
private void Build()
{
box = new HBox(false, 0);
box.SetSizeRequest(40, 40);
box.BorderWidth = 2;
button = new Button();
button.Clicked += cyclepoint;
lblpoints = new Label();
lblpoints.Text = "200";
lblpoints.ModifyFg(Gtk.StateType.Normal, new Gdk.Color(237, 52, 112));
button.Add(lblpoints);
button.ShowAll();
box.Add(this.button);
box.ShowAll();
this.Add(box);
}
So that is fine. Now I'm trying to attach the Signal so that whenever the Button is click it would change the Label Text for the particularly clicked button (as there will be multiple of the form.
Code I have for the signal:
private void cyclepoint(object sender, EventArgs args)
{
Console.WriteLine("Button Pressed!");
Console.WriteLine((Label)(((Button)sender).Child).Text);
}
Actual Output When I build the GUI and click the button
Button Pressed!
GtkLabel
Yet when I try to below to do a change the MonoDevelop IDe wont compile with error:
Error CS1061: 'Widget' does not contain a definition for 'Text' and no accessible extension method 'Text' accepting a first argument of type 'Widget' could be found (are you missing a using directive or an assembly reference?) (CS1061) (shump)
So I dont seem to be able to access the Text property of the Gtk.Label to change it's display Text. What is the correct way to go about doing this?
So in my regard. I dont believe I can access the "Child" element of the Gtk.Button object.
However, I've since discovered that I can access and edit the GTK.Label.Text property of the child Gtk.Label object directly from within the class. This will automatically update the Label with no necessary calls to Show() functions so will reflect the update immediately to boot! Furthermore, it also keeps the pango styling properties I had applied.
The end goal was to have a stylized countdown type of Button object that reduces the number as clicked and goal was accomplished.
private void cyclepoint(object sender, EventArgs args)
{
// Points is a different array that holds the increments of values
if (this.lblpoints.Text == points[10])
{
lblpoints.Text = points[0];
}
else
{
int nextval;
nextval = (Array.IndexOf(points, this.lblpoints.Text) + 1);
this.lblpoints.Text = points[nextval];
}
}

How can I count up the name of a Button with a Variable

I'm trying to make a battleship game in which the game field buttons all start with the letter A and then a number. Now I want to count up the numbers but still be able to do basic button functions like BackgroundImage.
What I'm doing now is just create a sting which adds the A with the number I receive from the function.
string btnr = "A";
btnr = btnr + Convert.ToString(nr);
string btnr = "A";
btnr = btnr + Convert.ToString(nr);
btnr.BackgroundImage = Image.FromFile(#"T:\E\_AUSTAUSCH\Com.Menu_OpenSurce\Battleship\Bilder\ACC_5_W.png");
This should change the Background image of the Button with the "nr" xx but I already get an error message saying:
Error 3 "string" contains no definition for "BackgroundImage", and no
extension method "BackgroundImage" could be found that accepts a first
argument of type "string". (Is there no Using directive or assembly
reference?)
Assuming WinForms, you can use Controls.Find to get a reference to the Button, no matter how deeply nested it is:
string btnName = "A" + nr.ToString();
Control ctl = this.Controls.Find(btnName, true).FirstOrDefault();
if (ctl != null && ctl is Button)
{
Button btn = (Button)ctl;
btn.BackgroundImage = Image.FromFile(#"T:\E\_AUSTAUSCH\Com.Menu_OpenSurce\Battleship\Bilder\ACC_5_W.png");
}
You are getting the button name. But you need to reference to the button object. To do this, you can use the controls property to select the button by name:
Please note that this example assumes that the button exists and the control is of type Button. Update: also assumes that the buttons are inmediate childs of the form
var button = (Button)Controls[btnr];
button.BackgroundImage =
Image.FromFile(#"T:\E\_AUSTAUSCH\Com.Menu_OpenSurce\Battleship\Bilder\ACC_5_W.png");

Having a reference to a property, Is there a way to grab a reference to the encompassing object?

I have extended the Label class as follows:
public class MyLabel: Label {
public Button btn;
public string mydata;
}
In my main program, I instantiated a new instance:
MyLabel lbl = new MyLabel();
lbl.mydata = "some data here";
lbl.btn = new Button();
lbl.btn.Click += new EventHandler(button_pressed);
this.Controls.Add(lbl); // Adds the label to the form
this.Controls.Add(lbl.btn); // Adds the button to the form
And I created a method to handle the button click event:
void button_pressed(Object sender, EventArgs e) {
Button btn = (Button)sender;
//Now I have an access to the property within MyLabel instance.
// but how can I access the parent object?
// I need to access the sibling property [mydata] string from here
btn.Siblings["mydata"] = "some other thing" ; //Something like this
MyLabel lbl = btn.ParentObject(); //Or something like this
lbl.mydata = "Some other thing";
}
This looks like WinForms, in which case either a UserControl or extending Button class might be a good way to go - just maintain a reference to the parent (a bit more complicated with UserControl, you'd need to define the click event on that control, otherwise you're back to "square 1") I like the Tag property solution as well, although there is an additional cast, and no guarantee of type safety (since Tag is an object, it can be anything by the time you try to access it).
However, let's say you're looking for a more general solution; let's also say that the class in question is sealed, has no Tag or similar purpose property, and a Controls collection is not available (or looping through it is not desirable for performance reasons). To my best knowledge, you can't determine parent object; but you can easily provide your own "Controls" style dictionary, mapping the Button to the parent:
public class MyLabel: Label {
public static Dictionary<Button, MyLabel> ParentMap = new Dictionary<Button, MyLabel>();
public Button btn;
public string mydata;
public void AddToParentMap() => ParentMap[btn] = this;
}
When you're creating an instance of MyLabel, just call the AddToParentMap() function (can't be done in constructor, because this pointer is not available until the object is created):
MyLabel lbl = new MyLabel();
lbl.AddToParentMap();
You can then just look it up, fast and easy, in your click event:
void button_pressed(Object sender, EventArgs e) {
Button btn = (Button)sender;
var label = MyLabel.ParentMap[btn];
//...
//Your code...
}
Unlike the Tag solution, type safety is guaranteed - you always know you're accessing a MyLabel object.
You can't access it through button instance but what you can do is to get MyLabel from Controls collection:
var lbl = this.Controls.OfType<MyLabel>().FirstOrDefault(c => c.btn == btn);
You can use the Tag property.
lbl.btn = new Button();
lbl.btn.Tag = lbl;
And then when you need it:
Button btn = (Button)sender;
Label lbl = (MyLabel)btn.Tag;

Use controls that are created at runtime

I am creating a textbox and a checkbox at runtime:
TextBox tb = new TextBox();
tb.Name = "txtPassword";
tb.PasswordChar = '*';
CheckBox cb = new CheckBox();
cb.Text = "Show Password";
cb.Name = "cbShowPassword";
cb.CheckedChanged += new EventHandler(cbShowPassword_CheckedChanged);
And I want to mask or unmask the password according to the checkbox:
private void cbShowPassword_CheckedChanged(object sender, EventArgs e)
{
txtPassword.PasswordChar = cbShowPassword.Checked ? '\0' : '*';
}
The problem is, it doesn't recognize txtPassword and cbShowPassword under cbShowPassword_CheckedChanged, since it is created in the code.
How can I make it work?
As it stands, you use a local variable tb in the method in which you instantiate the control. You can use that variable only in the method that instantiates the control. The fact that you gave the control a name does not mean that there is a variable defined named txtPassword.
You could continue this way, and dynamically look the control up from any other methods that wish to refer to it. However, that makes life harder than it needs to be. What you really want is a variable that refers to the control.
So, create a private member field of your class named txtPassword. Create the control like this:
txtPassword = new TextBox();
txtPassword.PasswordChar = '*';
....
To be really clear, txtPassword is a private member of your class, not a local variable.
Then you will be able to refer to it from other methods. Is there is a possibility that it might not have been created, test txtPassword against null.
Obviously you use the same technique for any other dynamically created controls.
I think you are mixing something up.
Did you add the controls to the parent form/controls?
Does the event fire ? (put a break point in there)
Try to use them as members instead of the name property and access this.cb and this.tb
You could use your form to find any Child controls that matches your newly created textboxes and Checkboxes.
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.controls(v=vs.110).aspx
Else you could set a reference to this objects in a property on the Form.

Categories

Resources