as Title
in my code,there are 2 buttons : "btnA" and "btnB"
When I press btnA , I expect that the ListView will show "EditItemTemplate_Edit" and do not show "EditItemTempPlate_Reset"
btnB is similar to btnA
I already added 2 EditItemTemplates in ListView like this :
<EditItemTemplate>
<tr class="EditItemTemplate" style="text-align: left;" id="EditItemTemplate_Eidt">
<td><asp:Label ID="Label_Factory" runat="server" Text='<%# Eval("test1") %>' /></td>
</tr>
<tr class="EditItemTemplate" style="text-align: left;" id="EditItemTemplate_Reset">
<td><asp:Label ID="Label3" runat="server" Text='<%# Eval("test2") %>' /></td>
</tr>
</EditItemTemplate>
I have already tried using script to set "display" -> "none" but it was not work
plz teach me how to make this work
thanks very much ~"~
I actually suggest in these cases to not even bother with the templates.
You can actually use less markup, less code, and less messy UI for the user.
Why not just let them tab around - make as many changes as they want - almost like a Excel sheet.
then have ONE save button - and on un-do button.
That way:
They just edit - not all this song and dance to hit edit + save buttons
So less UI, less code, and you can just tab around on ANY row - just edit.
Much less code.
So, say we have this markup for the listview.
<style> input {border:none}</style>
<asp:ListView ID="ListView1" runat="server" DataKeyNames="ID" >
<ItemTemplate>
<tr style="">
<td><asp:TextBox ID="txtFirst" runat="server" Text='<%# Eval("Firstname") %>' /></td>
<td><asp:TextBox ID="txtLast" runat="server" Text='<%# Eval("LastName") %>' /></td>
<td><asp:TextBox ID="txtCity" runat="server" Text='<%# Eval("City") %>' /></td>
<td><asp:CheckBox ID="Active" runat="server" Checked='<%# Eval("Active") %>' /></td>
</tr>
</ItemTemplate>
<LayoutTemplate>
<table id="itemPlaceholderContainer" runat="server" border="0" class="table table-hover">
<tr runat="server" style="">
<th runat="server">Firstname</th>
<th runat="server">LastName</th>
<th runat="server">City</th>
<th runat="server">Active</th>
</tr>
<tr id="itemPlaceholder" runat="server">
</tr>
</table>
</LayoutTemplate>
</asp:ListView>
<asp:Button ID="cmdSave" runat="server" Text="Save" CssClass="btn-primary" OnClick="cmdSave_Click1" />
<asp:Button ID="cmdAdd" runat="server" Text="Add Row" CssClass="btn-primary" style="margin-left:20px" OnClick="cmdAdd_Click1"/>
<br />
Note how MUCH LESS markup we have.
The code to load this lv looks like this:
private DataTable rstPeople = new DataTable();
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
LoadGrid();
ViewState["MyTable"] = rstPeople;
Session["test"] = "hello";
}
else
rstPeople = (DataTable)ViewState["MyTable"];
}
public void LoadGrid()
{
using (SqlCommand cmdSQL = new SqlCommand("SELECT * from People",
new SqlConnection(Properties.Settings.Default.TEST4)))
{
cmdSQL.Connection.Open();
rstPeople.Load(cmdSQL.ExecuteReader());
ListView1.DataSource = rstPeople;
ListView1.DataBind();
}
}
So we now have this:
So, you are now free to edit - even tab around almost like a Excel sheet. SUPER easy to edit the data - no special buttons to edit/save each row.
Very nice for the user - no huge UI and clicking and messing around to edit.
And the save button code, again REALLY simple since we send the WHOLE grid edits back to the database in one simple edit!!!
(and ONE update operation for the WHOLE grid!!!).
Save button code:
protected void cmdSave_Click1(object sender, EventArgs e)
{
// pull grid rows back to table.
foreach (ListViewItem rRow in ListView1.Items)
{
int RecordPtr = rRow.DataItemIndex;
DataRow OneDataRow;
OneDataRow = rstPeople.Rows[RecordPtr];
OneDataRow["FirstName"] = ((TextBox)rRow.FindControl("txtFirst")).Text;
OneDataRow["LastName"] = ((TextBox)rRow.FindControl("txtLast")).Text;
OneDataRow["City"] = ((TextBox)rRow.FindControl("txtCity")).Text;
OneDataRow["Active"] = ((CheckBox)rRow.FindControl("Active")).Checked;
}
// now send table back to database with updates
string strSQL = "SELECT ID, FirstName, LastName, City, Active from People WHERE ID = 0";
using (SqlCommand cmdSQL = new SqlCommand(strSQL,
new SqlConnection(Properties.Settings.Default.TEST4)))
{
cmdSQL.Connection.Open();
SqlDataAdapter daupdate = new SqlDataAdapter(cmdSQL);
SqlCommandBuilder cmdBuild = new SqlCommandBuilder(daupdate);
daupdate.Update(rstPeople);
}
}
So the trick? We persist the data table.
Then to save, you move grid back to data table, and then send the table BACK to the database in one simple update.
And the code to add a new row to the grid is ALSO very easy, we don't have to hit the database, but just add to the table, and then re-bind to the grid.
This code:
protected void cmdAdd_Click1(object sender, EventArgs e)
{
// add a new row to the grid
DataRow OneRow = rstPeople.Rows.Add();
ListView1.DataSource = rstPeople;
ListView1.DataBind();
}
So, notice how we save world poverty, save buckets of code, save buckets of mark-up, and we save buckets of messy UI in which the user has to hit edit/save over and over JUST to edit a few rows.
So, save code, save money, same markup, save messy user interface, provide a MUCH better and seamless user experience.
What more could you want?
Note how we defined the data table at the web page class level - by persisting that data table, then we get all of the wonderful and easy to use benefits above - including MUCH less code, much less markup, and much less user interaction required to edit a few simple rows of data.
And we ONLY send ONE update back to the database to save all rows - all of the dirty work here is thus done by .net for you, and you even wind up with not only MUCH less code, but we hit the database MUCH less for the update.
I did not add a un-do-edits button, but all it would do is call loadGrid again, and that would just re-load the data gain - and thus un-do any of our edits.
(so a un-do button would be a good idea here.)
Related
I have an aspx ListView control, a data pager for paging, paging is working fine. Now I have a dropdown to change page size and show the relevant records in listview. But dropdown not working properly.
I have total 14 records and when i go to 2nd page which has 4 records after that i change dropdown page size to 30 then it does not reflect listview and still showing same 4 records. It changes page number from 2nd to 1st only.
HTML:-
<asp:DropDownList ID="ddlCount" AutoPostBack="true" runat="server" CssClass="form-control"
SelectedIndexChanged="ddlCount_SelectedIndexChanged"> </asp:DropDownList>
<asp:ListView ID="lvParkingLots" runat="server" GroupPlaceholderID="grp" ItemPlaceholderID="item"
GroupItemCount="2" OnPagePropertiesChanging="lvPL_PagePropertiesChanging">
<LayoutTemplate>
<table class="table table-striped tblForm" id="gs">
<tr id="grp" runat="server">
</tr>
<tr class="pagination-listview">
<td></td>
<td style="float: right;">
<asp:DataPager ID="dp" runat="server" PagedControlID="lvParkingLots" PageSize="30">
<Fields>
<asp:NumericPagerField NextPageText="Next" PreviousPageText="Prev" />
</Fields>
</asp:DataPager>
</td>
</tr>
</table>
</LayoutTemplate>
C# function:-
protected void lvPL_PagePropertiesChanging(object sender, PagePropertiesChangingEventArgs e)
{
DataPager dp = (lvParkingLots.FindControl("dp") as DataPager);
dp.SetPageProperties(e.StartRowIndex, e.MaximumRows, false);
Binddata();
}
I have tried below code but not working..
protected void ddlCount_SelectedIndexChanged(object sender, EventArgs e)
{
Binddata();
}
The first argument to the event is of type object, here it should be the ListView, and the second argument will be PagePropertiesChangingEventArgs which is expecting StartRowIndex and MaximumRow, both are of type integer, so you can call that method like this:
int startRowIndex =2,MaximumRow=3;
lvPL_PagePropertiesChanging(lvSample, new PagePropertiesChangingEventArgs(startRowIndex , MaximumRow));
// where lvSample is the listview
In the case of the second example, you have to call the method like this:
ddlCount_SelectedIndexChanged(ddlCount, EventArgs.Empty);
I've got a ListView control that uses a custom data source. It will be a database soon, but for now I am still trying to get it running.
In the HTML of my form, I have the following code:
<%-- Ref: https://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.listview.layouttemplate.aspx --%>
<asp:ListView ID="lvOfficers" runat="server"
OnSelectedIndexChanging="lvOfficers_SelectedIndexChanging"
OnSelectedIndexChanged="lvOfficers_SelectedIndexChanged">
<LayoutTemplate>
<table id="tblOfficers">
<tr>
<th style="width:20%"></th>
<th colspan="2">Member Name</th>
<th style="width:20%"></th>
<th style="width:20%"></th>
</tr>
<tr>
<th>Title</th>
<th>Last</th>
<th>First</th>
<th>Phone</th>
<th>Email</th>
</tr>
<asp:PlaceHolder ID="itemPlaceHolder" runat="server" />
</table>
</LayoutTemplate>
<ItemTemplate>
<tr>
<td><asp:Label ID="lblRank" runat="server" Text='<#Eval("Rank") %>'></asp:Label></td>
<td><asp:Label ID="lblLast" runat="server" Text='<#Eval("LastName") %>'></asp:Label></td>
<td><asp:Label ID="lblFirst" runat="server" Text='<#Eval("FirstName") %>'></asp:Label></td>
<td><asp:Label ID="lblPhone" runat="server" Text='<#Eval("HomePhone") %>'></asp:Label></td>
<td><asp:Label ID="lblEmail1" runat="server" Text='<#Eval("PersonalEmail") %>'></asp:Label></td>
</tr>
</ItemTemplate>
</asp:ListView>
In the code behind with the Page_Load, I populate the data:
protected void Page_Load(object sender, EventArgs e) {
if (!IsPostBack) {
GetOfficers();
}
}
protected void GetOfficers() {
lvOfficers.DataSource = Personnel.GetOfficers();
lvOfficers.DataBind();
}
I can step through in Debug mode and see that there are 8 elements of type Person in a ListView that my "GetOfficers" data factory churns out.
The Person class contains subclasses:
Phone class: for {Home, Cell, Work},
Address class {Primary, Secondary} that contain ranking logic to indicate contact methods, and
Membership class. One tracks a member's ID, JoinDate, and Expiration while a second instance tracks the same elements for LifeMembership.
Thinking this complex Person class was causing my problems, I edited the GetOfficers() method to use an anonymous list:
protected void GetOfficers() {
var officers = Personnel.GetOfficers();
var data = from o in officers
select new {
o.Rank,
o.LastName,
o.FirstName,
o.HomePhone,
o.PersonalEmail,
};
//var data = (from o in officers
// select new {
// o.Rank,
// o.LastName,
// o.FirstName,
// o.HomePhone,
// o.PersonalEmail,
// }).OrderBy(o => o.Rank).OrderBy(o => o.LastName);
lvOfficers.DataSource = data;
lvOfficers.DataBind();
}
I was pretty sure that was going to solve my problems at first, so I included the two OrderBy clauses. When it did not work, I commented it out to try again, but I still got no success.
No matter what I seem to try, the page displays with the "Eval" text showing instead of the actual data.
I'm guessing the answer is something simple that I am overlooking because I use this same technique to populate the data in other pages in the same project.
How do I get my data to show up?
You need % at the start like this:-
'<%# Eval("Rank") %>'
you need to add % sign at the start of eval
'<%#Eval("FieldName")%>'
I have a table in DB:
NOTICE(NUM,TITLE,CONTENT)
I use Repeater Control in ASP to show all the notices in DB, like:
+----------+------------+|
|title1 (readmore)|
|
|title2 (readmore)|
|
|title3 (readmore)|
......
+------------------------+
All I want is: I read a "title" then I clicked on (readmore), the new page will be opened ( show detail's notice) with the "content" of that notice. How can I assign the num of notice without display it to define the notice in next page?
I just assign the title to property Text of a Label ID="TITLE" because I want to show the title of each notice.
All information I want to show in the this page is: title and the readmore( link to the next page). So that I don't know how to assign the num
My asp page: notice.asp
<asp:Repeater ID="RepDetails" runat="server" >
<HeaderTemplate>
<table style=" width:565px" cellpadding="0" class="borber">
</HeaderTemplate>
<ItemTemplate>
<tr>
<td>
<asp:Label ID="Title" runat="server" Text='<%#Eval("TITLE") %>' />
</td>
<td>
<asp:HyperLink ID="HyperLink1" runat="server" > (readmord)</asp:HyperLink>
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
My C# code:notice.asp.cs
private void BindRepeaterData()
{
string sql = "select num,title from NOTICE";
DataTable ds = l.EXECUTEQUERYSQL(sql);
RepDetails.DataSource = ds;
RepDetails.DataBind();
}
And the next page: detailnotice.asp.cs
private void GetNotice()
{
string sql = "select * from NOTICE where num=" ;// num= the num of notice I choose in notice.asp page.
}
How can I assign a num in Label without display it? What property of Label Control or I should use a other Control ?
Hope you understand what I say. If you don't, please ask?
Basically the same as Sain but using the NavigateURL
<asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl='<%# Eval("NUM","~/detailpage.aspx?id={0}") %>' > (readmord)</asp:HyperLink>
hi you can ues anchor tag in place of hyper link button. you can pass num in the query string to the detail page.
<a href='detailpage.aspx?id=<%#Eval("NUM") %>'> (readmord)</a>
On details page you can get query string value and fetch details from database.
int myKey = 0;
if (!string.IsNullOrEmpty(Request.QueryString["id"]))
{
myKey = int.Parse(Request.QueryString["id"]);
// Use myKey to retrieve record from database
}
I have a modalpopypextender that contains a grid view and I want populate it on button click which does this:
protected void btnViewRecipients_Click(object sender, EventArgs e)
{
ModalPopupExtender1.Show();
BindData();
}
Which is straight forward. BindData does this:
protected void BindData()
{
try
{
SqlCommand sqlCommand = new SqlCommand();
string connectionString = "Data Source=SERVER\\DB1;Initial Catalog=Survey;User ID=abcde;Password=12345;";
using (SqlConnection sqlConnection = new SqlConnection(connectionString))
{
sqlCommand = sqlConnection.CreateCommand();
sqlCommand.CommandText = "Select * From [Survey].[dbo].[data]";
SqlDataAdapter sda = new SqlDataAdapter(sqlCommand.CommandText, connectionString);
SqlCommandBuilder scb = new SqlCommandBuilder(sda);
//Create a DataTable to hold the query results.
//Fill the DataTable.
sda.Fill(dTable);
//Set the DataGridView DataSource.
gvRecords.DataSource = dTable;
gvRecords.DataBind();
sqlConnection.Close();
}
}
catch (SqlException ex)
{
//Console.WriteLine(ex.StackTrace);
}
}
Now this all works good and I get to see the grid with data. I then turned on autopaging and went ahead to create the call gvRecords_PageIndexChanged. I have also turned on EnableSortingAndPagingCallbacks.
protected void gvRecords_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
gvRecords.PageIndex = e.NewPageIndex;
gvRecords.DataSource = dTable;
gvRecords.DataBind();
}
This kinda works very strangely. I noticed that when I click a page number, the table becomes blank and shows me EmptyDataText that I defined earlier. But when I close the ModalPopupExtender and open it again (clicking the button again) it shows me the right page and data! e.g. if I clicked page 3, then get a blank table, now reopening the MPE will show me page 3's contents in a gridview. I guess that's the viewstate stored somewhere but why is it that the gridview will not show me the page right away?
I am really stuck at this and failing to understand what I'm missing!
Any help appreciated million times, I have searched and searched online for this but maybe it is so trivial and obvious that no one has ever needed to ask!?!
Edited I've been working with Modals, UpdatePanels and ListViews for years, we'll solve this, but it would be good to see the entire markup.
From your comments I'd suggest;
Put your entire modal markup in the UpdatePanel. Make sure to set the ID and UpdateMode to conditional;
<asp:UpdatePanel ID="upModal" runat="server" UpdateMode="Conditional">
<ContentTemplate>
</ContentTemplate>
</asp:UpdatePanel>
I usually use an ASP:Panel as my DIV inside my update panel;
<asp:Panel ID="pnlPopup" runat="server" CssClass="ModalPanel">
Then place your GridView (or in my case ListView) in your panel
In your code behind after you call your gvRecords.Databind(), call upModal.Update()
protected void gvRecords_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
gvRecords.PageIndex = e.NewPageIndex;
gvRecords.DataSource = dTable;
gvRecords.DataBind();
upModal.Update();
}
I got it working finally, I have had to set PopupControlID to upModal, the updatepanel's ID, as opposed to the inner panel. The targetcontrolID also had to point to a hidden button, as many have found you must when working with MPEs...
Anyway, here goes:
<asp:Button ID="hiddenButton" runat="server" Text="" style="display:none;" />
<ajaxToolkit:ModalPopupExtender ID="ModalPopupExtender1" runat="server" Enabled="True" TargetControlID="hiddenButton" PopupControlID="upModal" BehaviorID="modalbehavior" BackgroundCssClass="modalBackground" OnCancelScript="cancelClick();" CancelControlID="closePopup">
</ajaxToolkit:ModalPopupExtender>
<asp:UpdatePanel runat="server" ID="upModal" UpdateMode="Conditional">
<ContentTemplate>
<asp:Panel id="pnlPopup" runat="server" class="ModalPanel" >
<table cellpadding="5" cellspacing="5" class="topBanner" style="width:100%;">
<tr>
<td width="50">
<asp:LinkButton ID="closePopup" runat="server" onclick="LinkButton1_Click" CssClass="ClosePopupCls">Close
[x]</asp:LinkButton>
</td>
<td align="center">
<asp:Label ID="lbl" runat="server" Text="Status"></asp:Label>
</td>
<td width="25">
</td>
</tr>
<tr>
<td colspan="3">
<asp:GridView ID="gvRecords" runat="server" AllowPaging="True"
BackColor="White" EmptyDataText="No Record Found"
EnableSortingAndPagingCallbacks="True" ForeColor="GrayText" Height="600"
onpageindexchanging="gvRecords_PageIndexChanging" Width="800">
</asp:GridView>
</td>
</tr>
</table>
</asp:Panel>
</ContentTemplate>
</asp:UpdatePanel>
Ok guys, so I am trying to bind data into a dropdown list from c#. I am getting a Null error when trying to enter the data into the DDL's. I am using this code for the front end.
<asp:Repeater ID="RepeaterHardDrives" runat="server">
<HeaderTemplate>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
</HeaderTemplate>
<ItemTemplate>
<tr>
<td>
<asp:HiddenField ID="hidHardDrivesPackageDefaultID" runat="server" />
<asp:HiddenField ID="hidHardDrivesPackageDefaultPrice" runat="server" />
<span>
<asp:Label runat="server" ID="lbHardDiskPrice" Text="$00.00/mo"></asp:Label></span><label>Hard
Drive:</label><asp:DropDownList ID="ddHardDrive" DataTextField="ItemName" DataValueField="ProductItemID" runat="server" CssClass="lidropdown">
</asp:DropDownList>
<asp:ImageButton runat="server" ID="ShowHarddriveInfo" ImageUrl="/_Images/server_configurator_helpbutton.png"
OnClick="lnkShowHarddriveInfo_OnClick" /></div>
</td>
<td align="right">
<asp:Label runat="server" ID="lbHardDrivesPrice" />
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
<br />
</FooterTemplate>
</asp:Repeater>
for the backend I am trying to load a dynamic number of Dropdown lists into the repeater then databind them all with the same data.
public void PopulateHardDrives(int intSupportedDrives)
{
PreloadHardDriveRepeater(intSupportedDrives);
SqlConnection conn = new SqlConnection(WebConfigurationManager.ConnectionStrings["connstrname"].ConnectionString);
SqlCommand cmd = new SqlCommand("Prod_SelectIDNamePriceByCategory", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#CategoryCode", "Hard Drive");
DataTable dtHardDrives = new DataTable();
using (conn)
{
conn.Open();
SqlDataReader dr = cmd.ExecuteReader();
dtHardDrives.Load(dr);
ViewState.Add("dtHardDrives", dtHardDrives);
}
foreach (RepeaterItem riHardDrive in RepeaterHardDrives.Items)
{
DropDownList ddHardDrives = (DropDownList)riHardDrive.FindControl("ddHardDrives");
ddHardDrives.DataSource = dtHardDrives;//program gives NULL exception error here(object not set to instance of object however it know the count of the rows it is supposed to be pulling)
ddHardDrives.DataValueField = "ProductItemID";
ddHardDrives.DataTextField = "ItemName";
ddHardDrives.DataBind();
Label lbHardDrive = (Label)riHardDrive.FindControl("lbHardDrivesPrice");
lbHardDrive.Text = String.Format("{0:c}", Convert.ToDecimal("0.00"));
if (riHardDrive.ItemIndex != 0) //We do not want to allow None to be selected on the main drive
{
ddHardDrives.Items.Insert(0, "None");
}
}
}
and last but not least the function to setup the dynamic amount of DDL's looks like this
private void PreloadHardDriveRepeater(int intSupportedDrives)
{
int[] intArrDisks = new int[intSupportedDrives];
for (int intDiskCount = 0; intDiskCount < intArrDisks.Length; intDiskCount++)
{
intArrDisks[intDiskCount] = intDiskCount;
}
RepeaterHardDrives.DataSource = intArrDisks;
RepeaterHardDrives.DataBind();
}
I am calling a list of populate functions in a !page.isPostBack if statement and the only one that is not getting the data is this one with the Drown Lists. It gets the number of Rows(18) from the database, but it it throwing a Null error(Object reference not set to an instance of an object.) I have seen quite a few people have been running into this error while googling the problem, however I could not find a solution that worked for me. The PreloadHardDriveRepeater function seems to work fine when run alone it loads the correct amount of DDL's onto the page.
Thanks ahead of time.
Your control is "ddHardDrive":
<asp:DropDownList ID="ddHardDrive" DataTextField="ItemName" DataValueField="ProductItemID" runat="server" CssClass="lidropdown">
and your code is looking for "ddHardDrives"
riHardDrive.FindControl("ddHardDrives");
This would be easy to notice if you debugged into the function and looked at your variable values right before the exception is thrown.