I'm not really proficient in asp.net. I Have a asp based web application and I want to create a custom GridView in order to use it whenever I have a search box and reduce redundancy in my code.
I want to have this GridView below my textbox and on text changing the GridView shows mostly searched results and a "More" button for advance search which will open a new page. Can anybody help me how can I start?
Thanks.
Here a small example of how you could achieve this. First add the necessary items needed to do a search to the aspx page. Note that the buttons have an OnCommand so that you can send a CommandName along with them.
<asp:TextBox ID="SearchField" runat="server" MaxLength="50"></asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server"
ErrorMessage="A search term is required" ValidationGroup="Search"
ControlToValidate="SearchField">
</asp:RequiredFieldValidator>
<asp:Button ID="SearchButton" runat="server" Text="Search"
OnCommand="DoSearch_Command" CommandName="Search" ValidationGroup="Search" />
<asp:GridView ID="SearchResultsGridView" runat="server" AutoGenerateColumns="true"></asp:GridView>
<asp:Button ID="MoreButton" runat="server" Text="More"
OnCommand="DoSearch_Command" CommandName="More"/>
Now in the code behind you process the button clicks of Search and More. I created some dummy data with a List, but you need to replace that with the correct data source that holds your search results (List, DataTable etc).
protected void DoSearch_Command(object sender, CommandEventArgs e)
{
//create a new item to hold search results, in this case a list
List<string> searchResults = new List<string>();
//the text from the textbox that contains the search word
string searchTerm = SearchField.Text.Trim();
//hide the 'more' button
MoreButton.Visible = false;
//add some dummy data for testing
for (int i = 1; i <= 50; i++)
{
searchResults.Add("Search result " + i);
}
//if the results are more than 10 and the click is not from the 'more' button take 10 items
if (searchResults.Count > 10 && e.CommandName == "Search")
{
searchResults = searchResults.Take(10).ToList();
//show the more button
MoreButton.Visible = true;
}
//show results in gridview
SearchResultsGridView.DataSource = searchResults;
SearchResultsGridView.DataBind();
}
Related
I'm trying to create a quiz in web application in asp.net C# using a database. The quiz has 25 question and 5 answers and each answer has a number of points(totally agree(1),agree(2), not sure(3), disagree(4), totally disagree(5)).
The questions and answers are in a database.
What I want is when i click on the submit button to calculate the score from those questions and put the score in a table from my database.
I try to do a if (radiobutton1.checked){
score=2}
but it doesn't work because of the repeater...I guess i'm not sure.
I try to delete the repeater but when i done that the questions and answers do not display on the web page.
In my aspx file i write code to display my data from database like that(using a repeater and table):
<asp:Repeater ID="Repeater1" runat="server">
<ItemTemplate>
<table>
<tr>
<td> <%#Eval("IDq") %> ) <%#Eval("qustion") %></td></tr>
<tr>
<td>
<asp:RadioButton ID="RadioButton1" runat="server" Text='<%#Eval("ans1")%>' GroupName="quiz" Value="1"></asp:RadioButton>
<asp:RadioButton ID="RadioButton2" runat="server" Text='<%#Eval("ans2") %>' GroupName="quiz" Value="2"></asp:RadioButton>
<asp:RadioButton ID="RadioButton3" runat="server" Text='<%#Eval("an3") %>' GroupName="quiz" Value="3"></asp:RadioButton>
<asp:RadioButton ID="RadioButton4" runat="server" Text='<%#Eval("ans4") %>' GroupName="quiz" Value="4"></asp:RadioButton>
<asp:RadioButton ID="RadioButton5" runat="server" Text='<%#Eval("ans5") %>' GroupName="quiz" Value="5"></asp:RadioButton>
<br />
</td>
</tr> </table>
</ItemTemplate></asp:Repeater>
Ok, you have a good start.
And I am going to suggest that in place of the RadioGroup tag?
That DOES get you automatic ONLY one choice. The problem is we STILL will have to check all 5 controls.
A better control in this case to use what is called a RadioButtonList. It works VERY much like having used RadioGroup, but the REALLY nice part?
It is ONE control, and if there are 3 or 15 choices for Radio button group, it as ONE control returns
the index of the selection (0 to N)
the text value of the selection
the value value of the selection.
So I recommend using a RadioButton list - since it is "one thing" that returns the selections.
The "major" problem with the RadioButtonList is you CAN'T use those cool data bound expresisons ike you are using now (that was a good call/design on your part).
However, either we write a loop to "get/check" the 5 raido buttons, or we write a loop to fill the Radiobutton list - I think using code to fill out the RadioButton list is a better choice.
Also, you new - and I see you are attempting to use some "table and "tr" to help you lay out things. You don't really need this.
Now, because ALL of the above ideas saves us so much time, so much code? Well, then we can add extra code to say
show the score and results after we submit
tell the user they did NOT answer a question - they MUST!!!
heck, toss is a cool check box, or X box to show wrong or right.
Allow a question to only have say 2 answers - not always all 5
Ok first up, our table - it looks like this:
So, we have the IDq (id of question). The 1 to 5 possible answers, and then a column with the CORRECT answer.
Ok, now our markup. As I stated, since we reduced so much markup and code, then I added the message in big bold red that appears when a user did not answer all questions.
And I also added a "results" box that shows when you hit submit (number wrong, and correct).
So, now our Markup becomes like this:
<div style="width:35%">
<asp:Repeater ID="Repeater1" runat="server">
<ItemTemplate>
<div style="float:left">
<asp:Label ID="Question" runat="server"
Text = '<%# Eval("IDq").ToString + " ) " + Eval("question") %>'
Font-Size="X-Large">
</asp:Label>
</div>
<div style="float:right">
<img id="MyImage" runat="server" src="" height="48" width="48" />
</div>
<div style="clear:both">
<asp:RadioButtonList ID="RadioButtonList1" runat="server" RepeatDirection="Horizontal" ></asp:RadioButtonList>
</div>
<br />
<hr></hr>
</ItemTemplate>
</asp:Repeater>
<asp:Button ID="cmdDone" runat="server" Text="Submit" />
<div id="MyError" style="display:none;normal;color:red" runat="server">
<h2>You have not answered all questions</h2>
<h2>Please answer all questions before submitting</h2>
</div>
<div id="Results" runat="server" style="clear:both; display:none" >
<h2>Results</h2>
<asp:TextBox ID="MyCorrect" runat="server"></asp:TextBox>
<br />
<asp:TextBox ID="InCorrect" runat="server"></asp:TextBox>
</div>
</div>
so, not a lot of markup - and we added quite a bit new features.
I also tossed in the idea to show a check box for correct, and wrong - you can remove that part - but it does help you learn a lot here.
So, now when I run the code, I see this:
So note the questions I have correct. As I stated - you may well want to remove that.
And note the message that I not yet answered all questions.
So, as noted, we have a LITTLE bit more code to load up the Repeater, but less to check things after.
So, our code now looks like this:
private DataTable MyTable = new DataTable();
protected void Page_Load(object sender, System.EventArgs e)
{
if (IsPostBack == false)
{
LoadData();
ViewState["MyTable"] = MyTable;
}
else
MyTable = ViewState["MyTable"];
}
public void LoadData()
{
using (SqlCommand cmdSQL = new SqlCommand("SELECT * from tblQuestions ORDER BY IDq",
new SqlConnection(My.Settings.TEST4)))
{
cmdSQL.Connection.Open();
MyTable.Load(cmdSQL.ExecuteReader);
Repeater1.DataSource = MyTable;
Repeater1.DataBind();
}
}
protected void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item | e.Item.ItemType == ListItemType.AlternatingItem)
{
DataRow MyRow = MyTable.Rows(e.Item.ItemIndex);
RadioButtonList rBtnList = e.Item.FindControl("RadioButtonList1");
for (var i = 1; i <= 5; i++)
{
var strR = "ans" + i;
if (IsDBNull(MyRow(strR)) == false)
{
ListItem nItem = new ListItem(MyRow(strR), i);
rBtnList.Items.Add(nItem);
}
}
}
}
protected void cmdDone_Click(object sender, EventArgs e)
{
// check all rows - make sure all have a answer
// show check box for correct answers
// total up correct answers (count)
// total up wrong answers (count)
MyError.Style("Display") = "none";
int Correct = 0;
int Wrong = 0;
int NotAnser = 0;
foreach (RepeaterItem ritem in Repeater1.Items)
{
RadioButtonList RadioBut = ritem.FindControl("RadioButtonList1");
if (RadioBut.SelectedIndex >= 0)
{
HtmlImage MyImage = ritem.FindControl("MyImage");
if (MyTable.Rows(ritem.ItemIndex).Item("Answer") == RadioBut.SelectedIndex + 1)
{
Correct += 1;
MyImage.Src = "/Content/ok.png";
}
else
{
Wrong += 1;
MyImage.Src = "/Content/reject.png";
}
}
else
{
NotAnser += 1;
}
}
// if missed questions then display warning.
if (NotAnser > 0)
MyError.Style("Display") = "normal";
else
{
MyCorrect.Text = "Correct answers = " + Correct;
InCorrect.Text = "Wrong answers = " + Wrong;
Results.Style("Display") = "normal";
}
}
So you can see in that submit button code, we are NOW with great ease to loop the repeater, get the user answer, check against the table data.
And note the other trick - I persist MyTable into ViewState. I did this since I did not want to have to re-load the table each time - it just means for ANY button click, control and code behind? I ALWAYS have the data table at my fingertips
Now, given the above does total up the answer, then you would have to add 2-5 more lines of code to write out the total, or the results - it not clear if you plan to have some other table where you have say some student ID, or user id, and you save the total results of the test (or the correct count, or wrong count).
so, the final result looks like this:
Is there any way where we can reproduce the content of a panel.For example i have a panel which has two text box .On clicking more button i would like to have another panel below which again has two text box like the first one or add two text box into the existing panel.My end goal is to add controls as the user clicks on more button and get data from those controls .This is the controls inside the panel that i would like to reproduce
any possible way where i can add the controls as shown in the layout through server side ?Please help!
There are plenty ways to solve this. You could add proper DOM elements by yourself using plain JavaScript or jQuery, or use some JS MV* frameworks, like KnockoutJS (example: http://knockoutjs.com/examples/contactsEditor.html) or AngularJS.
you can obviously add dynamic controls from code behind on button click event of 'more button'.
Click Here for more references:
If you want to achieve this on client side using jQuery, then 'closest()' (to find the source element/row to be repeated nearby to the add/remove button etc., especially if it is in a tabular/grid format) in conjunction with 'clone()' function, (to make a copy of the source element/row) and then you can paste the clone inside the target container.
The following link might help you achieve what you want:
jQuery Clone table row
But doing this in Asp.Net WebForms should be much straight forward.
Also, please be noted that, it would always be much helpful to get a quicker answer by specifying more details(eg., MVC, WebForms etc. in the description, what trials you did to find/fix the problem) and that help save other's time as well. For more info: https://stackoverflow.com/questions/how-to-ask
try this
your aspx page add
<asp:TextBox runat="server" ID="TextBox1" />
<asp:TextBox runat="server" ID="TextBox2" />
<asp:Button Text="Add" ID="btnAdd" OnClick="btnAdd_Click" runat="server" />
<asp:Repeater ID="rpt" runat="server">
<ItemTemplate>
<asp:TextBox runat="server" ID="txt1" Text='<%# Eval("str1") %>' />
<asp:TextBox runat="server" ID="txt2" Text='<%# Eval("str2") %>' /><br />
</ItemTemplate>
</asp:Repeater>
and in code behind
protected void btnAdd_Click(object sender, EventArgs e)
{
List<temp> lst = GetItemFromRpt();
lst.Add(new temp
{
str1=TextBox1.Text,
str2 = TextBox2.Text
});
rpt.DataSource = lst;
rpt.DataBind();
}
private List<temp> GetItemFromRpt()
{
List<temp> lst = new List<temp>();
for (int i = 0; i < rpt.Items.Count; i++)
{
temp obj = new temp();
obj.str1 = ((TextBox)rpt.Items[i].FindControl("txt1")).Text;
obj.str2 = ((TextBox)rpt.Items[i].FindControl("txt2")).Text;
lst.Add(obj);
}
return lst;
}
public class temp // instead of temp you can use whatever your entity class you need
{
public string str1 { get; set; }
public string str2 { get; set; }
}
I've been trying to get this working for a couple of hours now but nothing from google could help me fix the problem.
I have a very simple repeater control:
<asp:Panel ID="userDefDiv" Visible="false" runat="server">
<asp:Repeater ID="userDefRepeater" EnableViewstate="false" runat="server">
<ItemTemplate>
<asp:TextBox ID="TextBox1" runat="server" EnableViewState="false"></asp:TextBox><br/>
</ItemTemplate>
</asp:Repeater>
</asp:Panel>
the userDefDiv panel is inside another panel, which is inside contentPLaceHolder.
the parent panel to userDefDiv does NOT have the "enableviewstate="false"".
So.
Everything on this page happens after a couple of linkbuttons_click. so nothing happens during page_load. And after i click another linkbutton i want to get the data from the different textboxes that is within the repeater.
C# code:
This is the code to create all the repeater items.
public void createUserDef()
{
DataTable userDefData;
userDefData = ..... (data from Database.)
userDefDiv.Visible = true;
userDefRepeater.DataSource = userDefData;
userDefRepeater.DataBind();
}
The code for the linkbutton:
protected void linkButton_Click(object sender, EventArgs e)
{
createUserDef();
Label2.Visible = true;
foreach (RepeaterItem item in userDefRepeater.Items)
{
TextBox box = (TextBox)item.FindControl("TextBox1");
string b = box.Text;
Label2.Text += b + " . ";
}
}
As you see i create the repeater once again during the click. But the only thing i can read in label2. is a a number of " .", on dot for each textbox.
but the text from the textbox is empty..
What am I doing wrong??
thanks for reading!
Mattias
SOLUTION:
add EnableVIewState="true" to textbox & repeater.
Dont call call dataBind() before you get the values.
Thanks!
You need to set EnableViewState to 'true' for linkbuttons to work properly in a repeater
I have a ListView setup with LinqDataSource and a button that triggers search function. To avoid display data on page_load, I set ListView's DataSourceID in the Click event of the search button, bind it and set result data in LinqDataSource's Selecting event. It works as I expected but It does't look pretty to set DataSourceId in the button Click event every time the search button is clicked. How can I do this in a better and clearer way?
ASPX code:
<asp:LinqDataSource ID="LinqDataSource1" runat="server"
ContextTypeName="WebApplication1.DataClasses1DataContext" EntityTypeName=""
TableName="Persons" onselecting="LinqDataSource1_Selecting">
</asp:LinqDataSource>
<asp:ListView ID="ListView1" runat="server" >...</asp:ListView>
<asp:Button ID="Search" Text="Search" runat="server" Click="Search_Clicked"/>
ASPX.CS code:
protected void Search_Clicked(object sender, EventArgs e)
{
ListView1.DataSourceID = LinqDataSource1.ID;
ListView1.DataBind();
}
protected void LinqDataSource1_Selecting(object sender, LinqDataSourceSelectEventArgs e)
{
//Search Criteria from CheckBoxList and TextBox applied here.
DataClasses1DataContext data = new DataClasses1DataContext();
var query = from result in data.Persons
where result.ID > 2
select result;
e.Result = query;
}
I honestly don't see anything wrong with your approach, however, if you don't like it, an alternate approach would be to just statically set the DataSourceID in your ListView markup as usual, but set Visible="False", and only make it visible once the button has been clicked.
I have a FormView which contains 5 dynamic DropDownLists. By dynamic, I mean the lists of dropdowns can be increased or decreased - depending on how many questions I have in my DB.
When I click the save button, I'm able to retrieve and store the content of the text boxes. But I'm not able to retrieve the DropDownLists.
One of the problems is that the ID of the DropDownLists changes name after I click the Save Button.
Why? Because upon Databinding of my DropDownLists, I rename the ID's so that I can identify which is which and store the appropriate data in the DB.
I'm not sure if I'm "attacking" this all wrong.
Here's my aspx code:
<asp:FormView runat="server" (...)>
//Lots of textfields here
<asp:Repeater runat="server" id="myRepeater"> //Datasource is bound in codebehind.
<ItemTemplate>
<li>
<div class="value"> <asp:DropDownList id="score" runat="server" OnDataBinding="hotelCriterias_DataBinding" /> </div>
</li>
</ItemTemplate>
</asp:Repeater>
</asp:FormView>
Here I rename the ID's and databind the datasource
protected void myDropDownList_DataBinding(object sender, EventArgs e)
{
DropDownList ddl = (DropDownList)(sender);
ddl.ID = "question" + Eval("questionID").ToString(); //Rename ID to 'question1, question2...)
Repeater rep = (Repeater)myFormView.FindControl("myRepeater");
rep.DataSource = this.dtQuestions;
rep.DataBind();
}
Try using an ObservableCollection object class as an intermediary between your drop down list and DB access.
By setting the ObservableCollection based class to be the data context for the list and handling a DataContextChanged event, you will always know what data is being displayed without having to worry about keeping track of where it is displayed.
When you hit save button, you need to iterate your repeater, should be like
protected void btnSave_Click(object sender, EventArgs e)
{
if (Repeater1.Items.Count > 0)
{
for (int count = 0; count < Repeater1.Items.Count; count++)
{
DropDownList ddl = (DropDownList)Repeater1.Items[count].FindControl("ddl");
ddl.SelectedValue//
}
}
}