I am generating x amount of buttons and I give all of them a unique name.
After all those are generated, I want to edit one of them without regenerating them so I was wondering if I could get a component by its name?
I am using WinForms
Yes:
Control myControl = Controls.Find("textBox1");
Now, beware that you have to do proper casting hen found, because Find returns a control.
You can use Controls property of your form (or some container control on your form). With LINQ you can select buttons and then find first button with required name:
var button1 = Controls.OfType<Button>().FirstOrDefault(b => b.Name == "button1");
Or if you want to search child controls recursively
var button1 = Controls.Find("button1", true)
.OfType<Button>()
.FirstOrDefault();
Without LINQ you can use method Find(string key, bool searchAllChildren) of ControlCollection:
Control[] controls = Controls.Find("button1", true);
if (controls.Length > 0)
{
Button button1 = controls[0] as Button;
}
Button btn1 = (Button)(Controls.Find("btnName"));
This will get the required button and will save the button attributes into a new Button btn1
After all those are generated, I want to edit one of them without
regenerating them so I was wondering if I could get a component by its
name?
var myButton = Controls.Find("buttonName", true).FirstOrDefault(); //Gets control by name
if(myButton != null)
{
if (myButton.GetType() == typeof(Button)) //Check if selected control is of type Button
{
//Edit button here...
}
else
{
//Control isn't a button
}
}
else
{
//Control not found.
}
Make sure you add a reference to: linq.
Related
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");
I've got some embedded user controls in this project I'm stuck with and while trying to access a button state in the parent control my return value isn't what I'm expecting.
var parentControl = (OrderDetail)this.Parent.Parent;
// set return based on the OrderDetail control button state
UltraButton btn = parentControl.Controls.Find("btnReturn", true).FirstOrDefault() as UltraButton;
That always returns btn.Enabled = true back to me, even though when the form is done loading the button I am referencing here is not enabled. Is there a lifecycle thing I am just not aware of here?
Delving into winforms is rare for me, so I'm sure I'm missing something, just not sure what it is yet.
Thanks!
Placed my code into the OnVisibleChanged event.
protected override void OnVisibleChanged(EventArgs e)
{
base.OnVisibleChanged(e);
if (Visible && !Disposing)
{
// set return change option based on the OrderDetail control button state
UltraButton btn = parentControl.Controls.Find("btnReturn", true).FirstOrDefault() as UltraButton;
if (btn != null && (HasPermissions && btn.Enabled))
actionAllowed = true;
}
}
How to find dynamically created XAML component by Name in C#?
I created next button and put it into the Stack Panel.
var nextButton = new Button();
nextButton.Name = "NextBtn";
next.Children.Add(nextButton);
then tried to find it with
this.FindName("NextBtn")
and it always comes null.
What am I doing wrong?
Use RegisterName instead of nextButton.Name = "NextBtn";
var nextButton = new Button();
RegisterName("NextBtn", nextButton); // <-- here
next.Children.Add(nextButton);
You can then find it with:
this.FindName("NextBtn")
As Farhad Jabiyev mentioned I created duplicate.
As related question (FindName returning null) explaines
from this page https://msdn.microsoft.com/en-us/library/ms746659.aspx
Any additions to the element tree after initial loading and processing
must call the appropriate implementation of RegisterName for the class
that defines the XAML namescope. Otherwise, the added object cannot be
referenced by name through methods such as FindName. Merely setting a
Name property (or x:Name Attribute) does not register that name into
any XAML namescope.
You could find the button manually, for example:
foreach (var child in next.Children)
{
if (child is Button && (child as Button).Name == "NextBtn")
;// do what you want with this child
}
Or:
var btn = next.Children.OfType<Button>().FirstOrDefault(q => q.Name == "NextBtn");
if (btn != null)
;// do what you want
I have a RealWorld.Grids.FrozenGridView and after selecting several checkboxes (in the last column) on the grid I try to access the rows in the C# file to run some tasks on the selected rows, but the grid comes up as null, and when I try to findcontrol from the page based on the name of the grid the result is null.
gridname = (RealWorld.Grids.FrozenGridView)this.FindControl("gridname") as RealWorld.Grids.FrozenGridView;
the grid is located in an updatepanel so to access the grid I include the update panel in the find control as such:
UpdatePanel up1 = new UpdatePanel();
up1.ID = "updatepanelID";
Label gn = (Label)up1.FindControl("labelname");
I also tried:
label lbl = (Label)this.Page.FindControl("updatepanelid").FindControl("labelname") as Label;
this should happen in a button_click event
Does anyone have any experience with this type of issue?
Any help is appreciated!
The FindControl doesn't always work as expected. Try this recursive function and use your line of code that you have up top.
public static Control FindControlRecursive(Control ctlRoot, string sControlId)
{
// if this control is the one we are looking for, break from the recursion
// and return the control.
if (ctlRoot.ID == sControlId)
{
return ctlRoot;
}
// loop the child controls of this parent control and call recursively.
foreach (Control ctl in ctlRoot.Controls)
{
Control ctlFound = FindControlRecursive(ctl, sControlId);
// if we found the control, return it.
if (ctlFound != null)
{
return ctlFound;
}
}// we never found the control so just return null.
return null;
}
Your call would look something like this.
var ridname = (RealWorld.Grids.FrozenGridView)FindControl(this, "gridname") as RealWorld.Grids.FrozenGridView;
HEllo, I need to dynamically activate fields in a page according to the service that is going to be executed...
Let me explain:
There's a page with all the possible fields and a ListBox with all the selected services to be executed, then when the user selects which service to execute (change a car plate, for example), then I need to activate only the field(s) that the service require... (The realationship between Services and Fields are stored in a database).
public void CheckAll(int pService_Id, Control pPage)
{
foreach (Control control in pPage.Controls)
{
busExecutaServico vExecuta = new busExecutaServico();
if (vExecuta.EnableField(control.ID.ToString(), Convert.ToInt32(listBoxServices.SelectedValue)))
{
switch (control.GetType().ToString())
{
case "TextBox":
TextBox controleText = (TextBox)Page.FindControl(control.ID.ToString());
controleText.Enabled = true;
break;
Note that busExecutaServico is the class which contains the method (EnableField) for checking if the selected item matches any field on the database..
I can't seem to get the control.ID.ToString() to work properly (the ID always comes as NULL)
If anyone can help me solve this, or if there's another way (even if it's completely different from what i'm trying), it would be of great help. thanks
I like to use a recursive function for locating controls by either type or ID.
public Control FindControlRecursive(Control rootControl, string controlId)
{
if (rootControl.ID == controlId)
return rootControl;
foreach (Control control in rootControl.Controls)
{
Control foundControl = FindControlRecursive(control, controlId);
if (foundControl != null)
{
return foundControl;
}
}
return null;
}
public Control FindControlRecursive(Control rootControl, Type type)
{
if (rootControl.GetType().Equals(type))
return rootControl;
foreach (Control control in rootControl.Controls)
{
Control foundControl = FindControlRecursive(control, type);
if (foundControl != null)
{
return foundControl;
}
}
return null;
}
You can adapt these to first return a collection of controls, then process them later. Might be easier to keep track of what's happening.
I learned this technique here: http://www.west-wind.com/Weblog/posts/5127.aspx
Be aware that FindControl only searches the current naming container so Page.FindControl will only find controls that are added directly to Page. For example, if you had a repeater control that had the controls you were looking for and it was added to Page, you could find your repeater control via Page.FindControl but it wouldn't find child controls within your repeater, you'd have to recursively perform the FindControl on all container controls in the page.
This might seem a bit strange but it allows you to have controls with the same ID existing on the same page. For example, if you had 10 instances of a user control with textboxes within them called "MyName", you'd really want them to not being over-writing each other's 'MyName' fields!
Your code will come across a null for an ID unless every control has been given an ID.
Also why use:-
TextBox controleText = (TextBox)Page.FindControl(control.ID.ToString());
at all instead of:-
TextBox controleText = (TextBox)control;
and indeed since you only want to change the Enabled property consider:-
((WebControl)control).Enabled = False;
That I suspect will eliminate many case statements.
In your code you don't need to search any control - you already have it in 'control' variable. You even don't need to cast it to TextBox, just to a WebControl, just do this:
...
if (vExecuta.EnableField(control.ID.ToString(), Convert.ToInt32(listBoxServices.SelectedValue)))
((WebControl)control).Enabled = true;
P.S. control.ID is already string, so you should remove any ID.ToString() also.