I am creating a survey, it has 60 textboxes I need to require that at least 40 of these textboxes are filled in upon hitting the submit button, it doesn't matter which ones as long as 40 have text within them. Any ideas how to accomplish this with C# or maybe another way?
A few of my textboxes:
<div class="row">
<div class="span3">
<div class="control-group">
<asp:Label ID="SupperLbl" class="control-label required" runat="server" Text="Best Supper Club"></asp:Label>
<div class="controls">
<asp:TextBox ID="SupperTxtBox" class="span3" runat="server"></asp:TextBox>
</div>
</div>
</div>
<div class="span3">
<div class="control-group">
<asp:Label ID="YogurtLbl" class="control-label required" runat="server" Text="Best Place for Frozen Yogurt"></asp:Label>
<div class="controls">
<asp:TextBox ID="YogurtTxtBox" class="span3" runat="server"></asp:TextBox>
</div>
</div>
</div>
</div>
<div class="row">
<div class="span3">
<div class="control-group">
<asp:Label ID="Label1" class="control-label required" runat="server" Text="Best Place for Dessert"></asp:Label>
<div class="controls">
<asp:TextBox ID="DessertTxtBox" class="span3" runat="server"></asp:TextBox>
</div>
</div>
</div>
<div class="span3">
<div class="control-group">
<asp:Label ID="Label2" class="control-label required" runat="server" Text="Best Place for Chicken"></asp:Label>
<div class="controls">
<asp:TextBox ID="ChickenTxtBox" class="span3" runat="server"></asp:TextBox>
</div>
</div>
</div>
</div>
.....
Place your textboxes in an array, then do some validation.
//Place textboxes in array for easy access
TextBox[] validatedTexboxes = new TextBox[] {
textbox1, textbox2, textbox3, ...
};
//On submit, make sure 40 are filled in.
var filledTextboxes = validatedTexboxes.Count(x => !String.IsNullOrWhiteSpace(x.Text));
if (filledTextboxes > 40)
//Do Something
string[] txtArr = { "SupperTxtBox", "YogurtTxtBox", "DessertTxtBox" };
protected void Page_Load(object sender, EventArgs e)
{
string[] lblArr = { "Best Supper Club", "Best Place for Frozen Yogurt", "Best Place for Dessert" };
for (int i = 0; i < lblArr.Length; i++)
{
Label lbl = new Label();
lbl.Text = "<br>" + lblArr[i] + "<br>";
TextBox txt = new TextBox();
txt.ID = txtArr[i];
Form.Controls.Add(lbl);
Form.Controls.Add(txt);
}
}
protected void Button1_Click(object sender, EventArgs e)
{
int Count = 0;
foreach (string item in txtArr)
{
TextBox t = (TextBox)Form.FindControl(item);
if (t != null)
{
if (t.Text.Trim() != "")
Count++;
}
}
if (Count < 3)
{
Response.Write("<br>You fill " + Count + " textbox, Please fill 3 textbox!");
}
}
If you want the validation on the server side, you can loop recursively on all the controls of the page, take the textboxes and verify if at least 40 contains text.
For the recursive loop, you can use the extension method from this answer :
public static IEnumerable<T> FindControls<T>(this Control control, bool recurse) where T : Control
{
List<T> found = new List<T>();
Action<Control> search = null;
search = ctrl =>
{
foreach (Control child in ctrl.Controls)
{
if (typeof(T).IsAssignableFrom(child.GetType()))
{
found.Add((T)child);
}
if (recurse)
{
search(child);
}
}
};
search(control);
return found;
}
All you need to do now is get the array and verify that at least 40 of them contain text :
private bool AreAtLeast40TextBoxesFilled()
{
var allTextBoxes = this.Page.FindControls<TextBox>(true);
return allTextBoxes.Count(t => !string.IsNullOrWhiteSpace(t.Text)) >= 40;
}
Use Phil Haack's tutorials on MVC list model binding so you can keep track of the value and the id of the textbox in a list and then check the count on the server side.
http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx
If the total count of elements in the list is less than your limit than return a modelstate validation error and return the same view.
If you need a specific example let me know.
Related
<asp:Panel runat="server" ID="pnlDocUpload">
<div class="row">
<div class="col-md-4">
<div class="column-pad-bottom column-pad-top">Document Title:</div>
<div class="column-pad-bottom2"><asp:TextBox runat="server" ID="fuTitle1" CssClass="form-control"/></div>
<div class="column-pad-bottom2"><asp:TextBox runat="server" ID="fuTitle2" CssClass="form-control"/></div>
<div class="column-pad-bottom2"><asp:TextBox runat="server" ID="fuTitle3" CssClass="form-control"/></div>
<div class="column-pad-bottom2"><asp:TextBox runat="server" ID="fuTitle4" CssClass="form-control"/></div>
<div class="column-pad-bottom2"><asp:TextBox runat="server" ID="fuTitle5" CssClass="form-control"/></div>
<div class="column-pad-bottom2"><asp:TextBox runat="server" ID="fuTitle6" CssClass="form-control"/></div>
<div class="column-pad-bottom2"><asp:TextBox runat="server" ID="fuTitle7" CssClass="form-control"/></div>
<div class="column-pad-bottom2"><asp:TextBox runat="server" ID="fuTitle8" CssClass="form-control"/></div>
<div class="column-pad-bottom2"><asp:TextBox runat="server" ID="fuTitle9" CssClass="form-control"/></div>
<div class="column-pad-bottom2"><asp:TextBox runat="server" ID="fuTitle10" CssClass="form-control"/></div>
<div class="column-pad-bottom2"><asp:TextBox runat="server" ID="fuTitle11" CssClass="form-control"/></div>
<div class="column-pad-bottom2"><asp:TextBox runat="server" ID="fuTitle12" CssClass="form-control"/></div>
</div>
<H3> I tried using find controls it is always returning null </H3>
protected void btAddSection_Click(object sender, EventArgs e)
{
string path = "C:/Users/emahou1/Desktop/testfolder";
if (cbIsLink.Checked == true)
{
if (fuTitleLink.HasFile)
{
// it is other section has nothing to do with the 12 input tags
}
else
{
// get the link path from the text box and save it ??
}
}
else
{
for (int i = 0; i < Request.Files.Count; i++ )
{
string text = "";
for (int t = 1; t <= 5; t++)
{
TextBox tb = FindControl("fuTitle" + t.ToString()) as TextBox;
if (tb != null) text += tb.Text;
}
if (Request.Files[i].FileName.ToString() != "")
{
// here i will collect the files and the textbox values to submit them to database
}
}
}
}
I have 12 input tabs that I will use to upload files to the server, I am already looping throgh the input controls to get the files, but these text boxes i want to loop through them so I can capture the text entered by the user and use that text to rename each file being uploaded ....
How about using FindControl inside the panel. Something like this
for (int t = 1; t <= 5; t++)
{
TextBox tb = pnlDocUpload.FindControl("fuTitle" + t.ToString()) as TextBox;
if (tb != null) text += tb.Text + "<br>";
}
<div>Found <%=foodCount%> results</div>
<div class="row">
<%if (foodReports != null)
{ %>
<%int count = 0; %>
<% foreach (var f in foodReports)
{
if (f.NRF63 > 28)
style = "green";
if (f.NRF63 <= 28 && f.NRF63 >= 4.66)
style = "#fabb36";
if (f.NRF63 < 4.66)
style = "#c32032";
%>
<div class="col-xs-12 mar-bottom-xs">
<ul class="list-unstyled price-holder md-round bg-light pad-bottom-xs">
<li class="price-heading" style="background: <%=style%>;">
<div class="align-left pull-left">
<strong><%=f.desc.name%></strong>
<span class="txt"></span>
</div>
<div class="align-right pull-right">
<strong class="Price">Nutrition Index: <%=f.NRF63%></strong>
<span class="txt">P/USDA</span>
</div>
</li>
</ul>
</div>
<%count++; %>
<% }
} %>
</div>
Obviously I am new to Webforms. Is it at all possible to add linkbuttons to each value being displayed from foodReports and perform different actions based on which button was selected (by the index or whatever?)
Based on other answers I've looked at, I have tried adding with CommandArgument = "<% =count %>" but the CommandArgument literally just comes out as "<% =count %>" instead of getting specific indexes. Any solution that allows me to keep the styling of each listed item will work.
"I have tried adding with CommandArgument = "<% =count %>" but the CommandArgument literally just comes out as "<% =count %>" instead of getting specific indexes."
First
You're not NEW in WebForms, you know only the "other answers I've looked at".
So buy some book for beginners and in 1 week you will look at your question and will offer your life in sacrifice to the glory of Satan for having embarrassed your ancestors.
Joking... on not... maybe... ok, to the answer
Answer
Use model binding tecnology
Here i will demonstrate to you using Repeater and ObjectDataSource.
Data Access Object (DAO)
using MyWebApplication.Models;
namespace MyWebApplication.DAO
{
public class FoodDAO
{
public List<Food> GetFoodList()
{
var foodList = new List<Food>();
foodList.Add(new Food
{
Index = 1,
NRF63 = 13.4m,
Desc = new Desc { Name = "Potato" }
});
foodList.Add(new Food
{
Index = 2,
NRF63 = 2.15m,
Desc = new Desc { Name = "McDonalds" }
});
foodList.Add(new Food
{
Index = 3,
NRF63 = 8000,
Desc = new Desc { Name = "Bacon" }
});
return foodList;
}
}
}
Model
namespace MyWebApplication.Models
{
public class Food
{
public decimal NRF63 { get; set; }
public Desc Desc { get; set; }
public int Index { get; set; }
public string Style
{
get
{
if (NRF63 > 28)
{
return "green";
}
else if (NRF63 <= 28 && NRF63 >= 4.66m)
{
return "#fabb36";
}
else
{
return "#c32032";
}
}
}
}
public class Desc
{
public string Name { get; set; }
}
}
Designer View
<asp:Repeater ID="FoodRepeater" runat="server"
DataSourceID="FoodDataSource"
ItemType="MyWebApplication.Models.Food">
<HeaderTemplate>
<div class="row">
</HeaderTemplate>
<ItemTemplate>
<div class="col-xs-12 mar-bottom-xs">
<ul class="list-unstyled price-holder md-round bg-light pad-bottom-xs">
<li class="price-heading" style='<%# "background:" + Item.Style + ";" %>'>
<div class="align-left pull-left">
<strong><%# Item.Desc.Name %></strong>
<span class="txt"></span>
</div>
<div class="align-right pull-right">
<strong class="Price">Nutrition Index: <%# Item.NRF63.ToString("{0:0.00}") %></strong>
<span class="txt">P/USDA</span>
</div>
</li>
<li>
<asp:LinkButton ID="SomeLinkButton" runat="server"
CommandArgument='<%# Item.Index %>'
OnClick="SomeLinkButton_Click">
<%# Item.Index %>
</asp:LinkButton>
</li>
</ul>
</div>
</ItemTemplate>
<FooterTemplate>
</div>
</FooterTemplate>
</asp:Repeater>
<div class="row">
<asp:Label ID="lblFoodsCount" runat="server"></asp:Label>
</div>
<asp:ObjectDataSource ID="FoodDataSource" runat="server"
TypeName="MyWebApplication.DAO.FoodDAO"
DataObjectTypeName="MyWebApplication.Models.Food"
EnablePaging="false"
SelectMethod="GetFoodList"
OnSelected="FoodDataSource_Selected">
</asp:ObjectDataSource>
Code Behind
public partial class MyPage : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void SomeLinkButton_Click(object sender, EventArgs e)
{
var button = sender as LinkButton;
int index;
if (!int.TryParse(button.CommandArgument, out index))
return;
// Do something with 'index'
}
protected void FoodDataSource_Selected(object sender, ObjectDataSourceStatusEventArgs e)
{
lblFoodsCount.Text = "The server return " +
((IList<Food>)e.ReturnValue).Count + " foods";
}
}
I have an asp.net webfore application which on the page i have an accordion and in that it has some fields. On the first asp:textbox it has an onclick as it checks my db to see if the user exists or not. If they do an asp:Label is then displayed.
The issue i have is that when ever i click outside or tab out this field my accordion closes and i need it to stay open. I was think though is is possible to do this via JQuery even though my field has the onclick or do i need to add it to my code behind?
In my view i tried
$("#MainContent_txtRemoveUser").on("blur", function ()
{
if ($('#MainContent_txtRemoveUser').val() != '')
{
$('panel-collapse collapse').removeClass('collapse');
$(this).addClass('in');
}
});
but it doesn't work
In my code behind i tried
#region Checks if user exists in 'Users' db when field clicked out of
protected void txtRemoveUser_TextChanged(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(txtRemoveUser.Text))
{
string connection = ConfigurationManager.ConnectionStrings["PaydayLunchConnectionString1"].ConnectionString;
SqlConnection conn = new SqlConnection(connection);
conn.Open();
SqlCommand cmd = new SqlCommand("SELECT 1 FROM Users WHERE Name = #Name", conn);
cmd.Parameters.AddWithValue("#Name", txtRemoveUser.Text);
SqlDataReader rd = cmd.ExecuteReader();
if (rd.HasRows)
{
removeUserNotExist.Visible = false;
ScriptManager.RegisterStartupScript(this.Page, this.GetType(), "tmp", "<script type='text/javascript'>function endRequestHandler(sender, args){$('#collapseOne').collapse.in()};</script>", false);
}
else
{
removeUserNotExist.Visible = true;
ScriptManager.RegisterStartupScript(this.Page, this.GetType(), "tmp", "<script type='text/javascript'>function endRequestHandler(sender, args){$('#collapseOne').collapse.in()};</script>", false);
}
}
}
#endregion
but this too doesn't work
The HTML of my accordion is
<div id="RemoveUser" class="panel-group">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#collapseOne" class="accordion-toggle collapsed">Remove Users From The List</a>
</h3>
</div>
<div id="collapseOne" class="panel-collapse collapse">
<div class="panel-body">
<p>If you would like to remove yourself or someone else from the list, please populate all the fields below ensuring to enter the <b>FULL</b> name of the user (whether its you or another user) and then click the 'Remove From List' button.</p>
<asp:Label ID="removeUserNotExist" runat="server" Text="The user entered does not exist. Please try again." Visible="false" style="color: red"></asp:Label>
<div class="form-group">
<asp:Label runat="server" AssociatedControlID="txtRemoveUser" CssClass="col-sm-offset-2 col-sm-3 control-label">Enter Name To Be Removed</asp:Label>
<div class="col-sm-3">
<asp:TextBox runat="server" ID="txtRemoveUser" CssClass="form-control" AutoPostBack="true" OnTextChanged="txtRemoveUser_TextChanged" />
</div>
</div>
<div class="row">
<div class="col-sm-offset-8 col-sm-3" style="padding-left: 0px">
<asp:Button runat="server" ID="btnRemoveUser" Text="Remove From List" CssClass="btn btn-danger" data-toggle="modal" data-target="#removeUserModal" data-backdrop="static" data-keyboard="false" ToolTip="Click to remove the specified user from the payday lunch list." />
</div>
</div>
</div>
</div>
</div>
</div>
None of these appear to work. I may be completly wrong in what i have done though.
The state of the accordion is getting lost on postback (which gets triggered on the textbox's text change event). One way to handle this is to maintain the value in a hidden field and then use this value to reset the accordion.
In .aspx add
<asp:HiddenField runat="server" ID="SetAccVisible" />
Then the corresponding javascript changes to:
$('document').ready(function () {
var hdnFldId = '<%= SetAccVisible.ClientID %>';
$("#txtRemoveUser").on("blur", function () {
//Set value of hidden field to show panel after postback
$('#' + hdnFldId).val(true);
});
if ($('#' + hdnFldId).val() == 'true') {
showPanel();
//lets reset the value
$('#' + hdnFldId).val(false);
}
function showPanel() {
if ($('#MainContent_txtRemoveUser').val() != '') {
$('.panel-collapse').removeClass('collapse').addClass('in');
}
}
});
You are missing class selector to target element. It should be:
$('.panel-collapse.collapse').removeClass('collapse');
In your Jquery, you have a little problem with your selector :
$("#MainContent_txtRemoveUser").on("blur", function ()
{
if ($('#MainContent_txtRemoveUser').val() != '')
{
$('.panel-collapse .collapse').removeClass('collapse');
$(this).addClass('in');
}
});
You forget the point before the class selector ;)
You can read more about JQuery selector here =>
https://api.jquery.com/class-selector/
Also, you can optimize your Jquery code :
$("#MainContent_txtRemoveUser").on("blur", function ()
{
if ($(this).val()) // == if $(#MainContent_txtRemoveUser).val() != ""
{
$('.panel-collapse .collapse').removeClass('collapse');
$(this).addClass('in');
}
});
You check the value of the selector's function (#MainContent_txtRemoveUser")
You can use the '$(this)' selector for call it again, in the function. ^^
And, don't forgot you can use a breakpoint in your browser for check your javascript!
Hope I help you :p
I'm loading a repeater with data and then on a button click i'm trying to save the data.
Heres what I have but the tbDate.text or tbAmount.texts are always being reported back as "" instead of the values.
<asp:Repeater runat="server" ID="rptInstallments" OnItemDataBound="rptInstallments_ItemDataBound">
<ItemTemplate>
<div class="form-group">
<label class="control-label">Installment Amount</label>
<div class="controls">
<asp:TextBox runat="server" ID="txtAmount" CssClass="form-control"></asp:TextBox>
</div>
</div>
<div class="form-group">
<label class="control-label">Installment Date</label>
<div class="controls">
<asp:TextBox runat="server" ID="txtDate" CssClass="form-control datepicker"></asp:TextBox>
</div>
</div>
</ItemTemplate>
</asp:Repeater>
Heres the backend code:
protected void btGo_Click(object sender, EventArgs e)
{
foreach (RepeaterItem item in rptInstallments.Items)
{
TextBox tbDate = item.FindControl("txtDate") as TextBox;
TextBox tbAmount = item.FindControl("txtAmount") as TextBox;
String myAmount = tbAmount.Text;
String myDate = tbDate.Text;
var rInstall = dtInstall.NewSubPIDInstallmentsRow();
rInstall.SPID = SPID;
rInstall.InstallmentAmount = Convert.ToDecimal(myAmount);
rInstall.InstallmentDue = Convert.ToDateTime(myDate);
dtInstall.AddSubPIDInstallmentsRow(rInstall);
taInstall.Update(dtInstall);
}
}
EDIT
I'm hacking in the repeater to no real data source. Could this be the problem?
int[] RowCount = new int[numberOfInstallments];
rptInstallments.DataSource = RowCount;
rptInstallments.DataBind();
Add your code of Binding the Repeater control with in the if (!IsPostBack) condition of Page_load. This worked for me.
I need to write some code that places one of 3 choices of "blocks" of html in a specified place on the page. How can I do this?
I was thinking I can use single value databinding, but I don't think this is the correct way.
I'm using ASP.NET c#.
Edit: here is what it might look like:
MapPlaceholder.InnerHtml = #"<div class="mapContainer smallMap" id="smallGrid" runat="server" visible="false">
<div id="node1" class="gridBox" runat="server">
</div>
<div id="node2" class="gridBox" runat="server">
</div>
<div id="node3" class="gridBox" runat="server">
</div>
<div id="node4" class="gridBox" runat="server">
</div>
<div id="node5" class="gridBox" runat="server">
</div>
<div id="node6" class="gridBox" runat="server">
</div>
<div id="node7" class="gridBox" runat="server">
</div>
<div id="node8" class="gridBox" runat="server">
</div>
<div id="node9" class="gridBox" runat="server">
</div>
</div>";
and in the .aspx page:
<div id="MapPlaceholder" runat="server"></div>
One more thing, how can I tell C# to actually write the " in the string? It isnt working currently because it stop at the first " it finds.
Edit: I have another problem.
MapPlaceholder.InnerHtml = block1;
HtmlGenericControl smallGrid = (HtmlGenericControl)MapPlaceholder.FindControl("smallGrid");
containerName = "smallGrid";
smallGrid.Visible = true;
smallGrid.Attributes["Style"] = "background-image:url('" + du.getMapBackgroundImage(mapId) + "'); " + "width:300px; height:300px;";
containerName = "smallGrid";
This is what i am trying to do, but the FindControl always returns null. I debugged this and it seems that the html code is being added, but only after the pageload ends. Is there anyway i can tell c# to "render" the div so i can work with it like i need to?
To have double quotes in code, you need to have two of them when using # so it would be:
MapPlaceholder.InnerHtml = #"<div class=""mapContainer smallMap"" id=""smallGrid"" runat=""server"" visible=""false"">
<div id=""node1"" class=""gridBox"" runat=""server"">
</div>
<div id=""node2"" class=""gridBox"" runat=""server"">
</div>
<div id=""node3"" class=""gridBox"" runat=""server"">
</div>
<div id=""node4"" class=""gridBox"" runat=""server"">
</div>
<div id=""node5"" class=""gridBox"" runat=""server"">
</div>
<div id=""node6"" class=""gridBox"" runat=""server"">
</div>
<div id=""node7"" class=""gridBox"" runat=""server"">
</div>
<div id=""node8"" class=""gridBox"" runat=""server"">
</div>
<div id=""node9"" class=""gridBox"" runat=""server"">
</div>
</div>";
To your original question: have three strings with the possible "blocks" then assign the proper string:
string block1 = #"<div class=""mapContainer smallMap"">block 1</div>......";
string block2 = #"<div class=""mapContainer smallMap"">block 2</div>......";
string block3 = #"<div class=""mapContainer smallMap"">block 3</div>.......";
switch (myCond) {
case 1:
MapPlaceholder.InnerHtml= block1;
break;
case 2:
MapPlaceholder.InnerHtml= block2;
break;
case 3:
MapPlaceholder.InnerHtml= block3;
break;
}
Edit: looks like you need different approach. First, put all blocks inside the .aspx under MapPlaceholder control directly:
<div id="MapPlaceholder" runat="server">
<div class="mapContainer smallMap" id="smallGrid1" runat="server" visible="false">
block 1 contents here...
</div>
<div class="mapContainer smallMap" id="smallGrid2" runat="server" visible="false">
block 2 contents here...
</div>
<div class="mapContainer smallMap" id="smallGrid3" runat="server" visible="false">
block 3 contents here...
</div>
</div>
Having this, just show the proper control based on the condition:
switch (myCond) {
case 1:
smallGrid1.Visible = true;
break;
case 2:
smallGrid2.Visible = true;
break;
case 3:
smallGrid3.Visible = true;
break;
}
This way you don't have to mess with strings of raw HTML and can change the layout from the .aspx which is more convenient.
on Page Load you can insert what you need dynamically.
a tip: you can insert with a Label over its Text property an html block, javascript or jquery codes
Label myLabel = new Label();
myLabel.Text = #"html text";
Page.Controls.Add(myLabel);
If the question really is "how to place blocks of HTML onto the page" as a (very basic) example, you might find something like this useful:
ASPX code:
<div runat="server" id="mydiv"></div>
C# code:
mydiv.InnerHtml = "<span>hi</span>";
or
HtmlGenericControl c = new HtmlGenericControl("span");
c.InnerHtml = "hi";
mydiv.Controls.Add(c);
DataBinding is more for pushing dynamic values to page content from, e.g. a database.
The PlaceHolder control may be what you need:
http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.placeholder.aspx
<asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
protected void Button1_Click(object sender, EventArgs e)
{
Label NewLabel = new Label();
NewLabel.Text = "Hello World!";
PlaceHolder1.Controls.Add(NewLabel);
}
You can add HTML tags With concatenation of the string at label text or others
labelc.text="Html tags code here";