Wire Validator to run on specific button click - c#

I'm building a user control which has 2 buttons in it.
This is my html:
<form action="#">
<div id="container" runat="server" style="text-align: center;">
<asp:Button ID="btnAdd" runat="server" Text="+" Style="margin-left: 10px; margin-right: 10px"
OnClick="btnAdd_Click" />
</div>
<input type="submit" value="test" runat="server"/>
</form>
And in the code side I'm adding some new text boxes according to the user's clicking on the addBtn:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
//clear the session values
ViewState[VIEWSTATE_NAME] = null;
ViewState[VIEWSTATE_TEXT_BOX_LIST] = null;
return;
}
Debug.Write("here");
//if there is no text box list in the session - create a new one
if (ViewState[VIEWSTATE_TEXT_BOX_LIST] != null)
textboxIds = (List<string>)ViewState[VIEWSTATE_TEXT_BOX_LIST];
//get the name of the list
if (ViewState[VIEWSTATE_NAME] != null)
Name = (string)ViewState[VIEWSTATE_NAME];
}
protected void btnAdd_Click(object sender, EventArgs e)
{
//if there is no name - return
if (name == null)
return;
//add a new text field to the list
textboxIds.Add(name + "_" + (textboxIds.Count + 1));
//st text field id
//add the textbox list to the session
ViewState[VIEWSTATE_TEXT_BOX_LIST] = textboxIds;
//show the fields
ShowTextFields();
}
/// <summary>
/// Show all the text fields of this multiple text fields
/// </summary>
private void ShowTextFields()
{
Debug.Write("count" + textboxIds.Count);
foreach (string textBoxId in textboxIds)
{
//create textbox
TextBox textBox = new TextBox();
//create validator
RequiredFieldValidator validator = new RequiredFieldValidator();
//add textbox
textBox.ID = textBoxId;
container.Controls.Add(textBox);
container.Controls.Add(new LiteralControl("<br/>"));
//add validator
validator.ControlToValidate = textBox.ID;
validator.ErrorMessage = "Required";
container.Controls.Add(validator);
}
container.Controls.Remove(btnAdd);
container.Controls.Add(btnAdd);
}
Each of the added text boxes are required - there for I've added a validator to each on of them.
My problem is that the validator is running in the addBtn click, while I want it to run on the form submit button on click...
How can I wire it to happen ?

You can use ValidationGroup to determine what validates what and what triggers.
http://msdn.microsoft.com/en-us/library/ms227424%28v=vs.100%29.aspx
If you want the addBtn to not validate anything, you can add CausesValidation=false to the button.

Related

C# Repeater focusing the first element after DataSource is changed

I have a Repeater with a certain DataSource (consisting of a list of images). The Repeater holds ImageButtons.
The aspx:
<asp:Panel ID="panSearch" runat="server" ScrollBars="Vertical" BorderColor="#333333" BorderStyle="Inset" Width="500" Height="200">
<asp:Repeater ID="Repeater" runat="server">
<ItemTemplate>
<asp:ImageButton OnClick="imgSearchResult_Click" BackColor="#333333" ID="imgSearchResult" height="32" width="32" runat="server" ImageUrl='<%# Eval("ImageUrl") %>'/>
</ItemTemplate>
</asp:Repeater>
</asp:Panel>
Additionally, I have a TextBox, which has a TextChanged-event in code-behind. I do a few things in there and at the end, my Repeater's DataSource will be overwritten with a new List of images (those images are put into the ImageButtons).
Repeater.DataSource = ImageList;
Repeater.DataBind();
My problem: Whenever my Repeater.DataSource is changed, it "clicks" the first ImageButton inside the Repeater. How do I prevent that from happening?
Full code:
My TextBox:
<asp:TextBox ID="textSearch" runat="server" Width="80" OnTextChanged="textSearch_TextChanged" ForeColor="Black" />
My TextChanged event:
protected void textSearch_TextChanged(object sender, EventArgs e)
{
string[] filesindirectory = Directory.GetFiles(Server.MapPath("~/Images/ORAS"));
List<System.Web.UI.WebControls.Image> ImageList = new List<System.Web.UI.WebControls.Image>(filesindirectory.Count());
foreach (string item in filesindirectory)
{
System.Web.UI.WebControls.Image myImage= new System.Web.UI.WebControls.Image();
myImage.ImageUrl = (String.Format("~/Images/ORAS/{0}", System.IO.Path.GetFileName(item)));
ImageList.Add(myImage);
}
Repeater.DataSource = ImageList;
Repeater.DataBind();
}
When I click on an ImageButton inside the Repeater (which is executed when the text in my TextBox is changed):
protected void imgSearchResult_Click(object sender, ImageClickEventArgs e)
{
var selectedImage = sender as ImageButton;
if (img1.ImageUrl == "~/Images/ORAS/Empty/000.png")
{
img1.ImageUrl = selectedImage.ImageUrl;
}
else if (img2.ImageUrl == "~/Images/ORAS/Empty/000.png")
{
img2.ImageUrl = selectedImage.ImageUrl;
}
else if (img3.ImageUrl == "~/Images/ORAS/Empty/000.png")
{
img3.ImageUrl = selectedImage.ImageUrl;
}
else if (img4.ImageUrl == "~/Images/ORAS/Empty/000.png")
{
img4.ImageUrl = selectedImage.ImageUrl;
}
else if (img5.ImageUrl == "~/Images/ORAS/Empty/000.png")
{
img5.ImageUrl = selectedImage.ImageUrl;
}
else if (img6.ImageUrl == "~/Images/ORAS/Empty/000.png")
{
img6.ImageUrl = selectedImage.ImageUrl;
}
else
{
ErrorMessage("Please remove one Image first!", true);
}
}
Pageload:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
img1.ImageUrl = "~/Images/ORAS/Empty/000.png";
img2.ImageUrl = "~/Images/ORAS/Empty/000.png";
img3.ImageUrl = "~/Images/ORAS/Empty/000.png";
img4.ImageUrl = "~/Images/ORAS/Empty/000.png";
img5.ImageUrl = "~/Images/ORAS/Empty/000.png";
img6.ImageUrl = "~/Images/ORAS/Empty/000.png";
LoadImages();
}
}
(LoadImages is almost 1:1 what's in my TextChanged function)
I really am not sure how (why) ASP.NET WebForms does it, but if you hit Enter and the form posts back, it will find the first control that implements IPostBackEventHandler and execute whatever event is bound to that. ImageButton implements it and so that's why it keeps firing the click event even though you didn't click on it. And, once again, only if you hit Enter.
I think that behaviour happens because the data posted back - __EVENTTARGET and __EVENTARGUMENT - are empty. Then ASP.NET goes bonkers.
You can solve it by putting a dummy button at the top of the page (or masterpage) and hide it using the style attribute. so:
<asp:Button ID="dummy" runat="server" style="display:none" />
Then in the init or load of your page (or masterpage) put
Form.DefaultButton = dummy.UniqueID;
That will force the button to capture the enter press instead of the arbitrary image button.

How to make CheckBoxList works with LinkButton event?

The following code shows some checkboxes that if you choose any of them, it will be listed on the page.
The problem is that I want to use the "LinkButton" on the page that if I click on the link then the ckeckbox will be shown. When I use OnLoad="Page_Edit" in "asp:LinkButton", the checkboxlist works fine but I do not want the checkboxlist shows up all the time and I want it to show up by clicking on the "Click to work with checkbox!" link. if I use OnClick="Page_Edit", by choosing any of the checkboxes, the checkboxlist disappears. Any help would be appreciated.
<h3> CheckBoxList Constructor Example </h3>
<asp:LinkButton id="myid" runat="server" Text="Click to work with checkbox!" OnLoad="Page_Edit" OnClick="Page_Edit" /><br />
Select items from the CheckBoxList.
<br /><br />
<asp:PlaceHolder id="Place" runat="server"/>
<br /><br />
<asp:label id="Message" runat="server"/>
void Check_Clicked(Object sender, EventArgs e)
{
// Retrieve the CheckBoxList control from the Controls collection
// of the PlaceHolder control.
CheckBoxList checklist = (CheckBoxList)Place.FindControl("checkboxlist1");
// Make sure a control was found.
if(checklist != null)
{
Message.Text = "Selected Item(s):<br /><br />";
// Iterate through the Items collection of the CheckBoxList
// control and display the selected items.
for (int i=0; i<checklist.Items.Count; i++)
{
if (checklist.Items[i].Selected)
{
Message.Text += checklist.Items[i].Text + "<br />";
}
}
}
else
{
// Display an error message.
Message.Text = "Unable to find CheckBoxList control.";
}
}
void Page_Edit(Object sender, EventArgs e)
{
// Create a new CheckBoxList control.
CheckBoxList checklist = new CheckBoxList();
// Set the properties of the control.
checklist.ID = "checkboxlist1";
checklist.AutoPostBack = true;
checklist.CellPadding = 5;
checklist.CellSpacing = 5;
checklist.RepeatColumns = 2;
checklist.RepeatDirection = RepeatDirection.Vertical;
checklist.RepeatLayout = RepeatLayout.Flow;
checklist.TextAlign = TextAlign.Right;
// Populate the CheckBoxList control.
checklist.Items.Add(new ListItem("Item 1"));
checklist.Items.Add(new ListItem("Item 2"));
checklist.Items.Add(new ListItem("Item 3"));
checklist.Items.Add(new ListItem("Item 4"));
checklist.Items.Add(new ListItem("Item 5"));
checklist.Items.Add(new ListItem("Item 6"));
// Manually register the event-handling method for the
// SelectedIndexChanged event.
checklist.SelectedIndexChanged += new EventHandler(this.Check_Clicked);
// Add the control to the Controls collection of the
// PlaceHolder control.
Place.Controls.Add(checklist);
}
Get rid of OnLoad on the checkbox and linkbutton; OnLoad runs everytime and does not meet your condition of showing only when linkbutton clicked. Now if the items are always in the list everytime, I'd recommend just add the control to the markup:
<asp:CheckboxList .. Visible="false">
<Items>
<asp:ListItem Text="Item 1" />
</Items>
</asp:CheckBoxList>
Notice the visible property; in linkbutton onclick, then you set checkboxlistID.Visible = true, and it will appear to the user.
Better idea is to create a new CheckBoxList control on PageLoad method with IsPostBack checking.
protected void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack)
//create checkbox list
}
After that you should add only OnClick="Page_Edit" to link button and inside Page_Edit method try to change only Visible properties for example:
void Page_Edit(Object sender, EventArgs e)
{
if(yourCondition)
yourCheckBoxList.Visible = true;
else
yourCheckBoxList.Visible = false;
}
The solution would be to have both OnLoad and OnClick on "asp:linkButton" and in OnClick event we make the checklist visible. This way we have made the checkbox to be loaded to the page but invisible unless someone clicks on the link that makes it visible. Thank you all.

Dynamically Created Controls losing data after postback

Actually, I am Creating 1 TextBox on Pageload and adding that TextBox to Panel.
Now, I have a LinkButton like Add Another.
I am entering Text in that TextBox and if needed I need to Create New TextBox,by clicking Add Another LinkButton.
Actually, I am able to get the count and recreate the TextBoxes.
But,the Problem is that, My Entered text in the Previously Generated Textboxes is Missing.
Can Anyone,Suggest me a solution for this?
protected void Page_Load(object sender, EventArgs e)
{
try
{
if (!IsPostBack)
{
for (int i = 0; i < 5; i++)
{
TableRow row = new TableRow();
for (int j = 0; j < 5; j++)
{
TableCell cell = new TableCell();
TextBox tb = new TextBox();
tb.ID = "TextBoxRow_" + i + "Col_" + j;
cell.Controls.Add(tb);
row.Cells.Add(cell);
}
Table1.Rows.Add(row);
}
}
}
catch (Exception ex)
{
throw;
}
}
This is a Sample Code, the same code is written in Button_Click Also
protected void ASPxButton1_Click(object sender, EventArgs e)
{
int k = Table1.Controls.Count;
}
I am getting a Count=0 on Button_Click.
All you need to do is to re-instantiate / reinitialize dynamic controls before or within page load event each and every time during postback and add this control to page / forms / placeholders. Then, the posted data will automatically be assigned to the control by calling the LoadPostData method by the parent control.
check the article and how to write code for dynamic control -
How to maintain dynamic control events, data during postback in asp.net
When using dynamic controls, you must remember that they will exist only until the next postback.ASP.NET will not re-create a dynamically added control. If you need to re-create a control multiple times, you should perform the control creation in the PageLoad event handler ( As currently you are just creating only for first time the TextBox using Condition: !IsPostabck ). This has the additional benefit of allowing you to use view state with your dynamic control. Even though view state is normally restored before the Page.Load event, if you create a control in the handler for the PageLoad event, ASP.NET will apply any view state information that it has after the PageLoad event handler ends.
So, Remove the Condition: !IsPostback, So that each time the page Loads, The TextBox control is also created. You will also see the State of Text box saved after PageLoad handler completes. [ Obviously you have not disabled ViewState!!! ]
Example:
protected void Page_Load(object sender, EventArgs e)
{
TextBox txtBox = new TextBox();
// Assign some text and an ID so you can retrieve it later.
txtBox.ID = "newButton";
PlaceHolder1.Controls.Add(txtBox);
}
Now after running it, type anything in text box and see what happens when you click any button that causes postback. The Text Box still has maintained its State!!!
The dynamically generated control do not maintain state. You have to maintain it at your own. You can use some hidden field to keep the state of controls, which will be used on server side to extract the state. Asp.net uses hidden field to maintain the state between requests, you can see __VIEWSTATE in the source.
In ASP.NET pages, the view state represents the state of the page when
it was last processed on the server. It's used to build a call context
and retain values across two successive requests for the same page. By
default, the state is persisted on the client using a hidden field
added to the page and is restored on the server before the page
request is processed. The view state travels back and forth with the
page itself, but does not represent or contain any information that's
relevant to client-side page display, Reference.
Just remove this line
if (!IsPostBack)
This is My final answer after working a lot with Dynamic Controls
.aspx
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<div style="text-align: center">
<div style="background-color: Aqua; width: 250px;">
<br />
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:PlaceHolder runat="server" ID="myPlaceHolder"></asp:PlaceHolder>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="btnAddTextBox" EventName="Click" />
</Triggers>
</asp:UpdatePanel>
<br />
</div>
<br />
<asp:Button ID="btnAddTextBox" runat="server" Text="Add TextBox" OnClick="btnAddTextBox_Click" />
<br /><br />
<asp:UpdatePanel ID="UpdatePanel2" runat="server">
<ContentTemplate>
<asp:Button runat="server" ID="MyButton" Text="Get Values." OnClick="MyButton_Click" />
<br /><br />
<asp:Label runat="server" ID="MyLabel"></asp:Label>
</ContentTemplate>
</asp:UpdatePanel>
</div>
</form>
.aspx.cs
static int myCount = 0;
private TextBox[] dynamicTextBoxes;
protected void Page_PreInit(object sender, EventArgs e)
{
Control myControl = GetPostBackControl(this.Page);
if ((myControl != null))
{
if ((myControl.ClientID.ToString() == "btnAddTextBox"))
{
myCount = myCount + 1;
}
}
}
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
dynamicTextBoxes = new TextBox[myCount];
int i;
for (i = 0; i < myCount; i += 1)
{
TextBox textBox = new TextBox();
textBox.ID = "myTextBox" + i.ToString();
myPlaceHolder.Controls.Add(textBox);
dynamicTextBoxes[i] = textBox;
LiteralControl literalBreak = new LiteralControl("<br />");
myPlaceHolder.Controls.Add(literalBreak);
}
}
protected void btnAddTextBox_Click(object sender, EventArgs e)
{
// Handled in preInit due to event sequencing.
}
protected void MyButton_Click(object sender, EventArgs e)
{
MyLabel.Text = "";
foreach (TextBox tb in dynamicTextBoxes)
{
MyLabel.Text += tb.Text + " :: ";
}
}
public static Control GetPostBackControl(Page thePage)
{
Control myControl = null;
string ctrlName = thePage.Request.Params.Get("__EVENTTARGET");
if (((ctrlName != null) & (ctrlName != string.Empty)))
{
myControl = thePage.FindControl(ctrlName);
}
else
{
foreach (string Item in thePage.Request.Form)
{
Control c = thePage.FindControl(Item);
if (((c) is System.Web.UI.WebControls.Button))
{
myControl = c;
}
}
}
return myControl;
}
When you are working with dynamic controls they will not able to maintain its state during postback and their data lost Cause they dont have any viewstate to maintain their data.
You only need to maintain the created controls data into ViewState
dynamically and loads the data into page at the time of postback and you
done.
public Dictionary<Guid, string> UcList
{
get { return ViewState["MyUcIds"] != null ? (Dictionary<Guid, string>)ViewState["MyUcIds"] : new Dictionary<Guid, string>(); }
set { ViewState["MyUcIds"] = value; }
}
public void InitializeUC()
{
int index = 1;
foreach (var item in UcList)
{
var myUc = (UserControls_uc_MyUserControl)LoadControl("~/UserControls/uc_MyUserControl.ascx");
myUc.ID = item.Value;
pnlMyUC.Controls.AddAt(index, myUc);
index++;
}
}
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
LoadControl();
else
InitializeUC();
}
Actually, I have used Javascript for accomplishing my task.
and it goes like this :
<form id="form1" runat="server" enctype="multipart/form-data" method="post">
<span style="font-family: Arial">Click to add files</span>
<input id="Button1" type="button" value="add" onclick="AddFileUpload()" />
<br />
<br />
<div id="FileUploadContainer">
<!--FileUpload Controls will be added here -->
</div>
<asp:HiddenField ID="HdFirst1" runat="server" Value="" />
<br />
<asp:Button ID="btnUpload" runat="server" Text="Upload" OnClick="btnUpload_Click" />
</form>
Script :
<script type="text/javascript">
var counter = 0;
function AddFileUpload() {
var div = document.createElement('DIV');
div.innerHTML = '<input id="file' + counter + '"name = "file' + counter + '"type="text"/><input id="file' + counter + '" name = "file' + counter + '" type="file" /><input id="Button' + counter + '" type="button" value="Remove" onclick = "RemoveFileUpload(this)" />';
document.getElementById("FileUploadContainer").appendChild(div);
counter++;
}
function RemoveFileUpload(div) {
document.getElementById("FileUploadContainer").removeChild(div.parentNode);
}
function mydetails(div) {
var info;
for (var i = 0; i < counter; i++) {
var dd = document.getElementById('file' + i).value;
info = info + "~" + dd;
}
document.getElementById('<%= HdFirst1.ClientID %>').value = info;
}
</script>
and In the Upload_Click Button :
for (int i = 0; i < Request.Files.Count; i++)
{
string strname = HdFirst1.Value;
string[] txtval = strname.Split('~');
HttpPostedFile PostedFile = Request.Files[i];
if (PostedFile.ContentLength > 0)
{
string FileName = System.IO.Path.GetFileName(PostedFile.FileName);
// string textname=
//PostedFile.SaveAs(Server.MapPath("Files\\") + FileName);
}
}

How to get values from dynamically created textbox's in another click event in asp.net?

I'm adding dynamic text box's to my panel in page load event, But I'm not able to access text box's in button click event and it is showing panel controls count ZERO(0) in button click event. Please give me solution to access text box values in button click event .
Thanks in advise.
Add your control in the Init function:
<div id="Parent" runat="server">
</div>
<asp:Button ID="btnTest" runat="server" Text="Get text" OnClick="btnTest_Click" />
protected void Page_Init(object sender, EventArgs e)
{
TextBox textInput = new TextBox();
textInput.ID = "text1";
textInput.Text = "Test";
Parent.Controls.Add(textInput);
}
protected void btnTest_Click(object sender, EventArgs e)
{
Response.Write((Parent.FindControl("text1") as TextBox).Text);
}
Inside the EventHandler of the particular button
insert this
TextBox MyTextBox=new TextBox();
//Assigning the textbox ID name
MyTextBox.ID = "name" +""+ ViewState["val"] + i;
MyTextBox.Width = 440;
MyTextBox.Height = 40;
MyTextBox.TextMode = TextBoxMode.MultiLine;
this.Controls.Add(MyTextBox);

Having trouble changing from One Line Text Box to Multiple Line Text Box

I have a text box that will allow the user to enter multiple authors by separate them with semicolon. Initially the Text Box is one line but after the user type in the first semicolon the text box will change to multiple line.
I'm able to change the text box to multiple line only if I click on "TAB" or "ENTER" keys. Is there any way to do it just by clicking on the semicolon key?
This is the partial front end code:
<!-- Report Author(s) Name(s) -->
<div class="row">
<div class="leftSide">
<asp:Label ID="LabelAuthorName" runat="server" Text="Author" />
</div>
<div class="rightSide">
<asp:TextBox ID="TextBoxAuthorName" runat="server" ToolTip="Author1; Author2; ...."
OnTextChanged="TextBoxAuthorName_TextChanged" AutoPostBack="True" ></asp:TextBox>
</div>
</div>
This is the partial back-end code:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
TextBoxDocCreaDate.Text = DateTime.Now.ToString("D");
}
}
protected void TextBoxAuthorName_TextChanged(object sender, EventArgs e)
{
bool isSemicolonClick = false;
string context = TextBoxAuthorName.Text;
if (isSemicolonClick == false)
{
for (int i = 0; i < context.Length; i++)
{
if (char.Equals(context[i], ';'))
{
isSemicolonClick = true;
TextBoxAuthorName.TextMode = TextBoxMode.MultiLine;
}
}
}
}
You won't really be able to trap that server-side unless you do a postback after each keystroke. Suggest using a simple JavaScript onkeypress event to check for semi-colons and go from there.
function checkForSemiColon(e){
var watchedkey = e.keyCode? e.keyCode : e.charCode
if(watchedkey = 186).....
}
Then on your textbox, just call onkeypress=checkForSemiColor(event), if it equals 186 it's a semi colon.

Categories