I need this page to be very easily maintained, so I need most of the stuff to be programmatically generated. I need to create checkboxes next to normal Labels, without touching the .aspx file. right now I generate a list with all labels on my page called labels. Each label on my site has an ID beginning with lbl_, but the ones that are supposed to have a checkbox begin with lblx_. I then want to use something like this to create said checkboxes:
foreach (Label label in labels)
{
if (label.ID.Contains("lblx_"))
{
CheckBox cb = new CheckBox();
cb.ID = "cb_statistikname_" + label.ID;
label.Controls.AddAt(0, cb);
}
}
Right now this code replaces the labels, the same happens when I use label.Control.Add(cb)
You can use Page.Controls.AddAt() with combination of page.Page.Controls.IndexOf()
if(label.Parent != null && label.Parent.Controls.IndexOf(label) >= 0)
label.Parent.Controls.AddAt(label.Parent.Controls.IndexOf(label) + 1, cb);
Note :This should be done in Page PreInit events.
If you set the Text property in your Label control, basically all child controls get wiped out. See this answer: asp:label doesn't render children
Related
I have a class called "is-active" and it has a colored arrow that sticks out from the nav into the main content based on which link the user clicked. The code runs a foreach and pulls all the categories from the database. How do I get the "is-active" class to display only for the current link? I know it works since I put it in the openList control and it displayed on all five categories, I just don't know how to get it to display on only the selected category.
I tried attaching jQuery to do it but adding the linkbutton is done all in the code behind so I am not sure how to attach the two. Is this the only way or is there another way?
Thank you in advance for your help!
Below is my code for the categories and link button:
protected override void CreateChildControls()
{
LiteralControl openingDiv = new LiteralControl("<div id='MainPanel'>");
LiteralControl closingDiv = new LiteralControl("</div>");
this.Controls.Add(openingDiv);
foreach (DataRow dr in ds.Tables[0].Rows)
{
LiteralControl openList = new LiteralControl("<li class='" + dr["CategoryColor"].ToString() + "'>");
LiteralControl closeList = new LiteralControl("</li>");
Label lblNumber = new Label();
LinkButton myLinkButton = new LinkButton();
myLinkButton.Text = "<span class='number'>" + dr["CategoryNumber"] + "</span>"+ dr["CategoryName"].ToString();
myLinkButton.CommandArgument = dr["Category_ID"].ToString();
myLinkButton.Click += myLinkButton_Click;
this.Controls.Add(openList);
this.Controls.Add(myLinkButton);
this.Controls.Add(closeList);
}
this.Controls.Add(closingDiv);
}
void myLinkButton_Click(object sender, EventArgs e)
{
LinkButton btn = (LinkButton)(sender);
Session["CategoryID"] = btn.CommandArgument;
Response.Redirect(Request.RawUrl);
}
Its tricky because your response.redirecting in the button click handler which recreates the pages viewstate.
This means that your page will always appear as fresh and the fact a user has clicked that link has been lost.
as a workaround you could place the link id in a session variable before you response.redirect and then recall it when the page reloads.
then when in your loop, if the session variable matches the current button instance.id you set cssclass equal to is-active.
remember to clear the session variable too after you set the cssclass to is-active to avoid confusion in other pages.
also, you will have to do the id comparison after you add the button to the control tree, because this is where the system automatically generates the id for you. I can give you a full example if you wish.
keep in mind that this is a workaround and a different approach would be best.
by this I mean that if you were to use an ispostback wrapper instead of a redirect, then on postback you could set the id to isactive much easier.
Page lifecycle is an important thing to get your head around in .net if you wish to be more proficient, especially as you mention that your using ajax update panels.
Read this: http://msdn.microsoft.com/en-us/library/ms178472(VS.100).aspx it's a lot of information to take in, so bookmark it for later too as you will use it a lot.
I'm looking for solution for my problem. I want to change location for tabcontrol's TabButtons or add control assigned to tabpage but outside TabControl. TabPages are added dynamically. Example:
Form1___________ _ [] X
_______________________
Some TabPage content
Tab1 | Tab2 | Tab3 | < >
TextBox assigned to Tab's
________________________
So if I change tabs by clicking on Tab1,Tab2,Tab3 TabPage + TextBox content should change depending on Tab. The first idea was to put TabButtons on bottom and add ArrayList what contains TextBox content, catch TabControl change tab event and change TextBox content, but there was an issue with editing and adding that content. In few words: I wan't to put TabButtons between 2 controls(for example between two textboxes).Do you have any ideas?
If I understand what you're asking for... You want when you click on a tab, it controls two different things? Like two different text boxes?
If that is true, you should be able to do it like this.
foreach (thing in your ArrayList)
{
TabPage tabPage = new TabPage("Name of tab"); // Add a new tab page
RichTextBox rtb = new System.Windows.Forms.RichTextBox();//RTF box
TextBox tb = new System.Windows.Forms.TextBox(); //Text box
//Set up size, position and properties
rtb.LoadFile("some/Path/to/a/file");
//set up size, position of properties
tb.Text = "Some text I want to display";
tabPage.Controls.Add(rtb); //Add both boxes to that tab
tabPage.Controls.Add(tb);
tabControl1.TabPages.Add(tabPage); //Add that page to the tab control
}
Only thing you should have to mess around with is the layout. And make sure to have the tabControl added with the designer.
you can create your own textbox class which inherits from textbox class :
class MyOwnTextBox:TextBox
{
public int parent_tab;
}
So you can add your textbox by assigning a parent_tab id to them . so in tab button click event , you can do something like that :
foreach(MyOwnTextBox txt in this.Controls)
{
if(txt.parent_tab==1) txt.visible=false;
}
You could also place the tabs on the left or the right side of your tab control. That is not perfect, but would come closer to your idea than placing them above or below the tab control.
You can add a new tab page dynamically like this
tabControl1.TabPages.Add("My new Tab");
I'm not sure I understand exactly what your trying to do. If you want to change the tab from another object, just use:
TabController.SelectTab(0);
If you want to remove a TabPage and add it to another, use:
TabController.Controls.Remove(TabPage1);
TabController2.Controls.Add(TabPage1);
Edit: From further read, I think you want something like this:
this.TabController.ControlAdded += AddLinksToBottomOfTabs;
public void mainSettingsTabController_ControlAdded(object sender, ControlEventArgs e)
{
//Create label with e.Control.Name as the title and
//add it to wherever you want it added.
}
I have a series of of tabs that hold text boxes in them. Some of the tabs have a control that contains Text Boxes inside of a Scrollview as well. I am trying to iterate through the tabs and clear the content of the text boxes.
I was going to use this:
foreach(TabItem item in Tabs.Items)
{
ClearTextBoxes(this);
}
I then use this to clear to the text boxes:
TextBox tb = obj as TextBox;
if (tb != null)
tb.Text = "";
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
ClearTextBoxes(VisualTreeHelper.GetChild(obj, i));
}
It is currently only clearing the first tab and none of the rest.
Any ideas?
Use the LogicalTreeHelper. Only the items of the currently active tab are contained in the visual tree, therefore the visual tree helper is not the best choice for your task.
Iterating over the tab items is IMO not necessary, only if you have a lot of other controls not residing in the tab-items and therefore want to spare cpu power. As already mentioned by Bela R, there is an error in your call to ClearTextBoxes().
I think it should be ClearTextBoxes(item) and not ClearTextBoxes(this)
foreach(TabItem item in Tabs.Items)
{
ClearTextBoxes(item);
}
First I understand the need to build dynamic controls in the OnInit Section.
However, I read a document from Scott Guthrie?
http://scottonwriting.net/sowblog/archive/2004/10/08/162998.aspx
So I got the impression from these blogs that if you add the control to the container then modify the properties, you can get at the control in the Page_Load.
In a nutshell, I have a table with a fk back to the table creating a hierarchy.
I load 3 usercontrols the page with checkbox lists that relate back through the parent key.
Table like this:
create table myTbl
(
id int identity,
par_id int,
item_desc varchar(25)
other_desc_flag bit
)
What my clients need is the ability to make a checkbox selection.
The child set of textboxes will display based on the parent.
If the txt_flag is set, a checkbox entry will not be populated.
Instead, they want the desc label printed out with a textbox for response.
The user data is not kept in the table above by the way.
So the issue I have is these text responses can be at any level of the custom control.
So I created a class with a 3 items ( id, literal control, and a textbox ).
I then dynamically create the controls based on the selection at any particular level.
I read each level into a dataset, I iterate through the dataset looking for that flag.
I capture an index variable in the rows with this flag and I create a List class to hold the
id, text_desc. I then remove the row from the table in the dataset and bind the remaining items to the checkboxlist.
I then go back to my control and write out dynamically the controls.
But like all those before me, I am doing evil battle against the Page Cycle...lol.
I cannot see the controls. I plan to DataBind() my controls separately on load as I have not gotten to the point where I'm getting the clients reponses from the database. That's for another day. The placeholder with my dynamic controls is OtherPlaceHolder. I have tried setting the Viewstate to true and false.
Any pointers on how to get the # of items on postback into a session variable so I can create the controls on the OnInit section.
Here is the code. This is being run from a Master Page...
On the controls, I changed the < & > to [ ] because this page that attempts to put code into
a controlbox with scrollbars was cutting off that code.
[asp:UpdatePanel ID="UpdPanel" runat="server" EnableViewState="true" UpdateMode="Always"]
[ContentTemplate]
[asp:Table runat="server" ID="ContainerTbl"]
[asp:TableHeaderRow]
[asp:TableHeaderCell ColumnSpan="2" CssClass="tdCell"][asp:Literal ID="LitDesc" runat="server" Text="Level" /][/asp:TableHeaderCell]
[/asp:TableHeaderRow]
[asp:TableRow]
[asp:TableCell runat="server" ID="tblItems" VerticalAlign="top"]
[asp:PlaceHolder runat="server" ID="CtrlPlaceHolder"]
[asp:CheckBoxList ID="cboItems" Visible="false" runat="server" AutoPostBack="true"][/asp:CheckBoxList]
[asp:HiddenField ID="otherCnt" runat="server" /]
[/asp:PlaceHolder]
[asp:PlaceHolder runat="server" ID="OtherPlaceHolder" EnableViewState="false"]
[/asp:PlaceHolder]
[/asp:TableCell]
[/asp:TableRow]
[asp:TableRow]
[asp:TableCell VerticalAlign="top"]
[asp:Label ID="LabMsg" runat="server" CSSClass="tdCell" Font-Bold="true" Visible="false"/]
[/asp:TableCell]
[/asp:TableRow]
[/asp:Table]
[asp:HiddenField ID="hLevel" runat="server" Value="" /]
[/ContentTemplate]
[/asp:UpdatePanel]
private void WriteOutQuestions(List<Questions> qList)
{
int itemCnt = 1;
// clear any controls in other place holder first.
OtherPlaceHolder.Controls.Clear();
Table OTD = new Table();
foreach (Questions qst in qList)
{
// we're going to create the new control and add to
// the placeholder - OtherPlaceholder
// we'll then reference those controls and add the data to those
// controls.
// see dynamic control article: http://scottonwriting.net/sowblog/archive/2004/10/08/162998.aspx
HiddenField hItemId = new HiddenField();
TextBox txtItem = new TextBox();
LiteralControl ltcItem = new LiteralControl();
// add the new controls
string strItemId = "hItem" + Convert.ToString(itemCnt);
string strTxtItem = "txtItem" + Convert.ToString(itemCnt);
string strLtcItem = "ltcItem" + Convert.ToString(itemCnt);
hItemId.ID = strItemId;
hItemId.EnableViewState = true;
txtItem.ID = strTxtItem;
txtItem.EnableViewState = true;
ltcItem.ID = strLtcItem;
ltcItem.EnableViewState = true;
OTD.Controls.Add(OtherDescAddControl(OtherPlaceHolder, hItemId, ltcItem, txtItem));
// now reference the new added controls and set values from Question object...
++itemCnt;
}
OtherPlaceHolder.Controls.Add(OTD);
// now post data to controls...
itemCnt = 1;
foreach (Questions qst in qList)
{
string strItemId = "hItem" + Convert.ToString(itemCnt);
string strTxtItem = "txtItem" + Convert.ToString(itemCnt);
string strLtcItem = "ltcItem" + Convert.ToString(itemCnt);
HiddenField hfld = (HiddenField)OtherPlaceHolder.FindControl(strItemId);
TextBox txtBox = (TextBox)OtherPlaceHolder.FindControl(strTxtItem);
LiteralControl ltx = (LiteralControl)OtherPlaceHolder.FindControl(strLtcItem);
hfld.Value = qst.HFld.ToString();
txtBox.Text = qst.TxtBox;
txtBox.Attributes.Add("class", "txtBox");
ltx.Text = qst.Ltc.ToString();
++itemCnt;
}
//decrement itemCnt and populate box here...
--itemCnt;
HiddenField hfldCnt = (HiddenField)CtrlPlaceHolder.FindControl("otherCnt");
hfldCnt.Value = Convert.ToString(itemCnt);
hfldCnt.Visible = true;
}
On the assumption that when you say "I cannot see the controls" you mean that you're getting null references when you try to access them in the postback (rather than that the HTML doesn't contain them), have you tried using Page.EnsureChildControls()?
Ok If I understood your question right, you want to save your controls and load them back on postbacks. Here is what you can do:
List<HiddenField> HiddenFields = new List<HiddenField>{};
List<TextBox> TextBoxs = new List<TextBox>{};
List<LiteralControl> LiteralControls = new List<LiteralControl>{};
OTD.Controls.Add(OtherDescAddControl(OtherPlaceHolder, hItemId, ltcItem, txtItem));
// do this for all your items that you load to page (add them to your list).
HiddenFields.Add(hItemId);
// when you are done with loading all your controls to page, add your populated Lists to session.
Session["HiddenFields"] = HiddenFields;
//On Page_Init or Page_Load, simpy load them back IF **page is postback**.
If(Page.IsPostBack)
{
LoadControlsFromSession();
}
private void LoadControlsFromSession()
{
HiddenFields = Session["HiddenFields"] as List<HiddenFields>;
// Load all your List objects from session like above.
int counter = 0;
if(HiddenFields != null)
{
foreach(HiddenField hdnField in HiddenFields)
{
//load your objects with the same method you have from your List.
OTD.Controls.Add(OtherDescAddControl(OtherPlaceHolder, HiddenFields[counter], LiteralControls[counter], TextBoxs[counter]));
counter++;
}
}
}
I apologize for lack of clarity.
I believe I did try setting Session variables in my classes when I created the controls and they were null on postback. I tried to access the session variable in the page init and preload and zip.
I did find an interesting workaround to this problem. On page_unload I parsed through the controls into an arraylist of hashtables of the database id & user'sentered text answer.
I want to create a kind of 4 x 3 matrix with textboxes and checkboxes. Whether the element is checkbox or textbox depends upon the values in database.I want it to be dynamic. What is the best way to start?
// something like this but I need to fill in each elements of the matrix...
private void CreateSpecificControl(string requestedType)
{
if (requestedType == "CheckBox")
{
CheckBox control1 = new CheckBox();
control1.Click += new EventHandler(chk_CheckedChanged);
//TableLayout panel
layout.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 25));
layout.Controls.Add(control1);
}
else
{
Label control1 = new Label();
control1.Text = "Not a checkbox";
layout.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 25));
layout.Controls.Add(control1);
}
}
Use a usercontrol. See this tutorial.
At run time you can change the contents of the User control. There's a Controls collection in each user control that you can add or remove elements from. For example if you want to add check boxes just do somethign like this:
myUserControl.Controls.Add(new CheckBox());
Similarly elements can be removed from this collection, thus achieving a dynamic behaviour.