Hello all fellow programmers.
I wanna make a paging of a database each consisting of 5 items and using a query opening the page. When i click the button i wanna change the query of the database connection and refresh the datalist with the new data consisting to that query(new 5 items) that i made but somehow my code needs a bit of help. I am a basic c# programmer and every help welcomed.
ASP
<link rel="stylesheet" href="../Images/book-style.css" />
<link rel="stylesheet" href="../Images/form.css" />
<link rel="stylesheet" href="../Images/style.css" />
<span id="bookshead" />
<div style="margin-top:50px" >
<asp:DataList ID="DataList1" runat="server" DataKeyField="ID_AUTHOR" DataSourceID="SqlDataSource1" SeparatorStyle-Wrap="False">
<ItemTemplate>
<div class="books" style="width:530px;height:150px;margin-bottom:20px;border:1px dotted black;border-radius:5px;box-shadow:2px 2px 6px black;">
<p class="book" runat="server"><%# Eval("TITLE") %></p>
<p class="author"><%# Eval("NAME") %> <%# Eval("SURNAME") %></p>
<img class="book-image" runat="server" alt="book image" src='<%# Eval("imazhi") %>' style="width:85px;height:130px" />
<br />
<div class="addtowishlist" >
<a href="#" >Add to Wishlist</a>
</div>
</div>
</ItemTemplate>
</asp:DataList>
</div>
<asp:Label runat="server" ID="labe" Text="HELLLOO"></asp:Label>
<form id="ff" runat="server" >
<div id="Navigation" class="navigation">
<div id="leftnav">
<asp:Button ID="PreviousPageNav" runat="server" href="#bookshead" OnClick="updateBackward" Text="<< Librat e mëparshëm" />
<asp:Label ID="PagerLocation" runat="server" />
<asp:Button ID="NextPageNav" runat="server" href="#bookshead" OnClick="updateFoward" Text=" Librat e ardhshëm>>"/>
</div>
</div>
</form>
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:eLibraryPConnectionString %>" SelectCommand="Select *FROM (AUTHORS a JOIN BOOKS_AUTHORS ba ON a.ID_AUTHOR=ba.ID_AUTHOR) JOIN BOOKS b ON ba.ID_BOOK=b.ID_BOOK WHERE a.ID_AUTHOR>=1 AND a.ID_AUTHOR<=5"></asp:SqlDataSource>
</asp:Content>
AND The C#
private int firstItem=1;
private int lastItem=5;
public void updateFoward(object o, EventArgs e)
{
firstItem += 5;
lastItem += 5;
SqlDataSource sql = new SqlDataSource();
sql.ID = "SqlDataSource1";
sql.SelectCommand = "Select * FROM (AUTHORS a JOIN BOOKS_AUTHORS ba ON a.ID_AUTHOR=ba.ID_AUTHOR) JOIN BOOKS b ON ba.ID_BOOK=b.ID_BOOK WHERE a.ID_AUTHOR>=" + firstItem + "AND a.ID_AUTHOR<=" + lastItem;
labe.Text =sql.ID;
DataList1.DataBind();
}
public void updateBackward(object o,EventArgs e)
{
firstItem -= 5;
lastItem -= 5;
SqlDataSource sql = new SqlDataSource();
labe.Text = "Backward";
sql.ID = "SqlDataSource1";
sql.SelectCommand = "Select * FROM (AUTHORS a JOIN BOOKS_AUTHORS ba ON a.ID_AUTHOR=ba.ID_AUTHOR) JOIN BOOKS b ON ba.ID_BOOK=b.ID_BOOK WHERE a.ID_AUTHOR>=" + firstItem + "AND a.ID_AUTHOR<=" + lastItem;
DataList1.DataBind();
}
}
The first issue to address here is that the firstitem and lastitem variables are defined at the class level in your page. It's important to remember that every event in ASP.Net results in a completely new instance of the class, and runs the entire page lifecycle: not just the event code itself. Anything from a prior instance of the page class is gone. Therefore, you click the "updateForward" button, for example, and the existing code will always give results running from 6 to 10, regardless of how many times you click it.
The quick solution here is to store this data either in the Session or in ViewState, instead of in the class. I'll use the Session as an example going forward.
The second problem is code that looks like this:
sql.SelectCommand = "Select * FROM (AUTHORS a JOIN BOOKS_AUTHORS ba ON a.ID_AUTHOR=ba.ID_AUTHOR) JOIN BOOKS b ON ba.ID_BOOK=b.ID_BOOK WHERE a.ID_AUTHOR>=" + firstItem + "AND a.ID_AUTHOR<=" + lastItem;
There are actually two problems here. The first is easy enough to correct: there isn't any spacing before the word "AND" after your firstItem substitution. The second problem will take considerably more work: the "string concatenation to include parameters" technique leaves you open to sql injection, and should be avoided. The good news is that the solution for this major security issue will also have the nice side effect of making your datasource work again.
To get started, let's first look at some of the existing ASP markup:
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:eLibraryPConnectionString %>"
SelectCommand="Select * FROM (AUTHORS a JOIN BOOKS_AUTHORS ba ON a.ID_AUTHOR=ba.ID_AUTHOR) JOIN BOOKS b ON ba.ID_BOOK=b.ID_BOOK WHERE a.ID_AUTHOR>=1 AND a.ID_AUTHOR<=5">
</asp:SqlDataSource>
We want to change the markup to look like this:
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:eLibraryPConnectionString %>"
SelectCommand="Select * FROM (AUTHORS a JOIN BOOKS_AUTHORS ba ON a.ID_AUTHOR=ba.ID_AUTHOR) JOIN BOOKS b ON ba.ID_BOOK=b.ID_BOOK WHERE a.ID_AUTHOR>= #firstItem AND a.ID_AUTHOR<= #lastItem">
<SelectParameters>
<asp:SessionParameter name="firstItem" sessionfield="firstItem" type="Int32" />
<asp:SessionParameter name="lastItem" sessionfield="lastItem" type="Int32" />
</SelectParameters>
</asp:SqlDataSource>
If you wanted to use ViewState instead of the session, you could use an asp:ViewStateParameter instead. There are also asp:QueryStringParameters and some other options you can use.
The new markup tells the datasource about placeholders in the sql string, and also tells it where to find the data for those placeholders. The datasource will handle filling that data into the string itself... or rather, it won't. The great thing about query parameters done this way is that the parameter data is never substituted directly into the sql command, even on the database server, eliminating any possibility of sql injection attacks.
Now you can simplify your updateForward()/Backward() methods like this:
public void updateFoward(object o, EventArgs e)
{
Session["firstItem"] = (int)Session["firstItem"] + 5;
Session["lastItem"] = (int)Session["lastItem"] + 5;
DataList1.DataBind();
}
The udpateBackward() method will need a similar change. The switch to the long-form x = x + 5 instead of x += 5 is so that you can cast the Object Session value to an int at the proper point.
You'll also need code to seed the Session variables:
public void Page_Load(object o, EventArgs e)
{
if (!IsPostBack)
{
Session["firstItem"] = 1;
Session["lastItem"] = 5;
}
}
Related
I know the title might make my question look like a duplicate so please read the complete question first.
I have 3 dropdowns in my webform and based on those parameters the data is retrieved from the database and my gridview is populated. What I need is that once a result is displayed, if the user changes the parameters, the new retrieved data should be displayed below the old data. But currently my gridview is refreshing entirely and only the data based on new parameters is displayed.
I have read that one way is to use viewstate but I dont understand what it is. Can someone please help? Thank you.
Ok, so this is a difficult question. It is rather easy to filter, and have a cumulative filter.
So, say we have this screen:
And lots more rows.
So, I can say lets filter by a city.
So this:
Note how we do allow multiple city in the multi-select drop down.
So, I now have this:
Now, lets select those ONLY with a description.
So this:
And then say only active ones. So, this:
So, above is quite easy to setup. Note how any option NOT selected is left out of the critera.
but, a BIG problem exists in the above.
What happens if I want Active from say B.C. but NOT active from Alberta???
I can't do that, and hence your problem.
What we could do however is add a button to above to SAVE the resulting filter, and put the "list" of filters say into a list box or collection.
we then have a search button to search on our collection of filters.
Let me see if this can work - I'll add to above a "box" or collection of each filter.
I would think a union query with distinct row for each filter would do the trick.
So, above example is not too hard - a "cumulative" filter. In fact, the code patter for 2 or 15 filters is quite easy to do here.
However, adding up separate filter requests and combine them? That is somewhat difficult to do.
Edit: Multiple filters
so, while in above, I could say filter by city and get all active, but THEN I want to filter by another city, and get all NON active!!!
That's the problem here.
So, we would have to add code to SAVE the filter. And the HUGE problem with that is how then do we save each filter to "add up" each filter set we want?
We could try and save the raw SQL, but such SQL would be subject to sql injection, and we want to always use parameters.
So, we can and could adopt a design in which we SAVE the resulting SqlCommand object. And then merge the results.
So, now our UI becomes like this:
Lets grab and filter all those from city Edmonton, but Active,
so, this:
We now hit save filter and this:
And now we filter by say City = Banff, but don't care about active or not.
So we have this:
We then save that filter - and now we have this:
I now hit the filter button below the list of filters, and we get this:
So, how does this code work?
Well, I simple saved the Sqlcommand object to a collection (list), and thus combine the results.
So, first our markup at the top for the filter stuff.
<h4>Filters</h4>
<div style="float:left">
<asp:Label ID="Label1" runat="server" Text="Search Hotel"></asp:Label>
<br />
<asp:TextBox ID="txtHotel" runat="server"></asp:TextBox>
</div>
<div style="float:left;margin-left:20px">
<asp:Label ID="Label2" runat="server" Text="Search City"></asp:Label>
<br />
<asp:TextBox ID="txtCity" runat="server"></asp:TextBox>
</div>
<div style="float:left;margin-left:20px">
<asp:Label ID="Label3" runat="server" Text="Must Have Description"></asp:Label>
<br />
<asp:CheckBox ID="chkDescripiton" runat="server" />
</div>
<div style="float:left;margin-left:20px">
<asp:Label ID="Label4" runat="server" Text="Show only Active Hotels"></asp:Label>
<br />
<asp:CheckBox ID="chkActiveOnly" runat="server" />
</div>
<div style="float:left;margin-left:20px">
<asp:Button ID="cmdSearch" runat="server" Text="Search" CssClass="btn" OnClick="cmdSearch_Click"/>
</div>
<div style="float:left;margin-left:20px">
<asp:Button ID="cmdClear" runat="server" Text="Clear Fitler" CssClass="btn" OnClick="cmdClear_Click"/>
</div>
<div style="float:left;margin-left:20px">
<asp:Button ID="cmdTest" runat="server" Text="Save Filter"
CssClass="btn" OnClick="cmdTest_Click"
OnClientClick="return myfilterprompt()"
/>
<asp:HiddenField ID="HFilterName" runat="server" ClientIDMode="Static"/>
<script>
function myfilterprompt() {
sFilter = ""
sFilter = prompt('Enter name for filter ')
if ( (sFilter === null) || (sFilter === "") ){
return false
}
$('#HFilterName').val(sFilter)
return true
}
</script>
</div>
<div style="float:left;margin-left:30px;width:190px">
<asp:ListBox ID="lstFilters" runat="server" Width="100%" Height="100px"
DataTextField="sFilterName" >
</asp:ListBox>
<asp:Button ID="cmdMultiFilter" runat="server" Text="Filter"
CssClass="btn" OnClick="cmdMultiFilter_Click" style="float:left" />
<asp:Button ID="cmdMultiClear" runat="server" Text="Clear"
CssClass="btn" OnClick="cmdMultiClear_Click" style="float:right"/>
</div>
then below above is our grid:
<asp:GridView ID="GridView1" runat="server"
AutoGenerateColumns="False" DataKeyNames="ID"
CssClass="table" Width="60%" ShowHeaderWhenEmpty="true">
<Columns>
<asp:BoundField DataField="FirstName" HeaderText="FirstName" />
<asp:BoundField DataField="LastName" HeaderText="LastName" />
<asp:BoundField DataField="HotelName" HeaderText="HotelName" />
<asp:BoundField DataField="City" HeaderText="City" />
<asp:BoundField DataField="Province" HeaderText="Province" />
<asp:BoundField DataField="Description" HeaderText="Description" />
<asp:BoundField DataField="Active" HeaderText="Active" />
</Columns>
</asp:GridView>
So, code to load:
List<MyFilter> MyFilters = new List<MyFilter>();
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack == false)
{
SqlCommand cmdSQL = new
SqlCommand("SELECT * FROM tblHotels WHERE ID = 0");
LoadGrid(cmdSQL);
Session["MyFilters"] = MyFilters;
}
else
MyFilters = (List<MyFilter>)Session["MyFilters"];
}
public void LoadGrid(SqlCommand cmdSQL)
{
DataTable rstData = MyRstP(cmdSQL);
GridView1.DataSource = rstData;
GridView1.DataBind();
}
And now our search button:
protected void cmdSearch_Click(object sender, EventArgs e)
{
SqlCommand cmdSQL = GetMyCommand();
LoadGrid(cmdSQL);
}
SqlCommand GetMyCommand()
{
string strSQL = "SELECT * FROM tblHotels ";
string strORDER = " ORDER BY HotelName";
string strFilter = "";
SqlCommand cmdSQL = new SqlCommand();
if (txtHotel.Text != "")
{
strFilter = "(HotelName like #HotelName + '%')";
cmdSQL.Parameters.Add("#HotelName", SqlDbType.NVarChar).Value = txtHotel.Text;
}
if (txtCity.Text != "")
{
if (strFilter != "") strFilter += " AND ";
strFilter += "(City Like #City + '%') ";
cmdSQL.Parameters.Add("#City", SqlDbType.NVarChar).Value = txtCity.Text;
}
if (chkActiveOnly.Checked)
{
if (strFilter != "") strFilter += " AND ";
strFilter += "(Active = 1)";
}
if (chkDescripiton.Checked)
{
if (strFilter != "") strFilter += " AND ";
strFilter += "(Description is not null)";
}
if (strFilter != "") strSQL += " WHERE " + strFilter;
strSQL += strORDER;
cmdSQL.CommandText = strSQL;
return cmdSQL;
}
And now our save the filter button code:
protected void cmdTest_Click(object sender, EventArgs e)
{
MyFilter OneFilter = new MyFilter();
OneFilter.sFilterName = HFilterName.Value;
OneFilter.cmdSQL = GetMyCommand();
MyFilters.Add(OneFilter);
lstFilters.DataSource = MyFilters;
lstFilters.DataBind();
}
public class MyFilter
{
public string sFilterName { get; set; }
public SqlCommand cmdSQL = new SqlCommand();
}
And our multi-filter code button.
Now, for large data sets - not a great idea, but a start:
protected void cmdMultiFilter_Click(object sender, EventArgs e)
{
List<DataTable> MyTables = new List<DataTable>();
foreach (MyFilter OneFilter in MyFilters)
{
DataTable rstDT = MyRstP(OneFilter.cmdSQL);
MyTables.Add(rstDT);
}
DataTable rstData = MyTables[0];
for (int i = 1;i < MyTables.Count;i++)
{
rstData.Merge(MyTables[i]);
}
GridView1.DataSource = rstData;
GridView1.DataBind();
}
so, you can build list up of "filters" and display them in a listbox and then have a filter button that merges all of the filtering.
And one more helper routine I used:
public DataTable MyRstP(SqlCommand cmdSQL)
{
DataTable rstData = new DataTable();
using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
{
using (cmdSQL)
{
cmdSQL.Connection = conn;
conn.Open();
rstData.Load(cmdSQL.ExecuteReader());
}
}
return rstData;
}
These systems can be really nice. Often a group of managers will say, lets grab all customers from west coast. Yuk - too many. Ok, only those with purchases in last 2 months - ah, that's nice.
then they say, lets get all customers who never purchased anything, but from the south - and add those to the list - but only active on our mailing list.
So, this type of slice and dice - get some of those, and then get some of these, and then combine them?
This type of business query system and being able to combine these, and those, and them, and then toss in a few more? Often they will keep going say until such time they get say 10,000 results (which happens to be how many catalogs they have left they would like to send out).
So, I solved my problem by using a little outside the box thinking. I am posting it here for anyone visiting this question or having a same problem in the future could see this:
So what I did is that I extracted the data from the database based on the parameters selected by the user from the dropdowns. In the database, I had created a temp table to store the extracted temporarily. So I inserted the data into that temporary table and used that table to populate the gridview. I had to add a reset button, when the user clicked it the all the data is deleted from the temp table and also the page reset to its default with gridview not visible and dropdowns having no selection.
Attempting to create a Storyboard in which user stories (list item) can be dragged and dropped from one ListView to another. Depending on which ListView the item is dropped into, the item's status is then updated in database.
Below are the data sources for each list view. Items from database displayed in corresponding ListView based on the status field. Status can be one of four: NULL, Started, Blocked, Completed
<asp:SqlDataSource ID="return_stories" runat="server" ConnectionString='<%$ ConnectionStrings:Scrumdog_Millionaire.Properties.Settings.DB_CONN %>'
SelectCommand="SELECT stories.storyID, stories.sprintID, stories.story_name, stories.status, users.first_name FROM stories INNER JOIN users ON stories.userID = users.userID WHERE stories.status IS NULL">
</asp:SqlDataSource>
<asp:SqlDataSource ID="return_started_stories" runat="server" ConnectionString='<%$ ConnectionStrings:Scrumdog_Millionaire.Properties.Settings.DB_CONN %>'
SelectCommand="SELECT stories.storyID, stories.sprintID, stories.story_name, stories.status, users.first_name FROM stories INNER JOIN users ON stories.userID = users.userID WHERE stories.status='Started'">
</asp:SqlDataSource>
<asp:SqlDataSource ID="return_blocked_stories" runat="server" ConnectionString='<%$ ConnectionStrings:Scrumdog_Millionaire.Properties.Settings.DB_CONN %>'
SelectCommand="SELECT stories.storyID, stories.sprintID, stories.story_name, stories.status, stories.blocked_description, users.first_name FROM stories INNER JOIN users ON stories.userID = users.userID WHERE stories.status='Blocked'">
</asp:SqlDataSource>
<asp:SqlDataSource ID="return_complete_stories" runat="server" ConnectionString='<%$ ConnectionStrings:Scrumdog_Millionaire.Properties.Settings.DB_CONN %>'
SelectCommand="SELECT stories.storyID, stories.sprintID, stories.story_name, stories.status, stories.blocked_description, users.first_name FROM stories INNER JOIN users ON stories.userID = users.userID WHERE stories.status='Completed'">
</asp:SqlDataSource>
Example of one of the ListViews:
<div class="pure-u-1 pure-u-md-1-3">
<div class="pricing-table pricing-table-biz pricing-table-selected">
<div class="pricing-table-header">
<h2>Started</h2>
</div>
<ul class="pricing-table-list" ondrop="drop(event)" ondragover="allowDrop(event)" dropzone="true" data-autodividers="true">
<asp:ListView ID="display_started_stories" runat="server" DataSourceID="return_started_stories">
<EmptyDataTemplate>
<span>Currently no stories for this sprint with status set to 'Started'.</span>
</EmptyDataTemplate>
<ItemTemplate>
<div class="block" style="width: 150px; background-color: lightgreen; padding: 10px; margin: 10px" draggable="true" ondragstart="dragStart(event)">
<li>
<asp:Label Text='<%# String.Format("<b>Task:</b>{0} <b>Assigned To:</b> {1}", Eval("story_name"), Eval("first_name")) %>' runat="server" ID="story_startedlabel" draggable="true" ondragstart="dragStart(event)"/>
</li>
</div>
</ItemTemplate>
</asp:ListView>
</ul>
</div>
</div>
Using javascript I have so far been able to drag items between lists however I am unsure how to trigger an update method in code behind file. Also uncertain whether best option is to use ondrop or ondragenter Event.
<script>
function dragStart(event) {
event.dataTransfer.setData("text/plain", event.target.id);
document.getElementById("demo").innerHTML = "Started to drag the selected story";
}
function allowDrop(event) {
event.preventDefault();
}
function drop(event) {
event.preventDefault();
var data = event.dataTransfer.getData("text/plain");
event.target.appendChild(document.getElementById(data));
document.getElementById("demo").innerHTML = "The story was dropped";
document.getElementById("story_blockedlabel").ondragleave();
}
function myFunction(variable) {
var s = document.getElementById(variable);
s.value = "Started";
}
myFunction("story_blockedlabel");
</script>
First time using stackoverflow so I apologize in advance if my description is too vague. Any help would be much appreciated or another suggestions on how to achieve this functionality would be much appreciated.Image of current HTML when rendered
Framework: ASP.NET 4.5 | Database: MSMMS
My demo application is supposed to populate textboxes with dynamic data when a selection is made from a dropdown list. I've added a button, that when pressed fires, an OnClick event that is supposed to assign values from the DB to the appropriate textboxes. Right now my code looks like:
protected void btnChoose_Click(object sender, EventArgs e)
{
API_DatabaseEntities1 db = new API_DatabaseEntities1();
var customer = (from c in db.Customers
where c.CustomerID == 4
select c).FirstOrDefault();
if (customer == null)
{
return;
}
if (ddlCustomer.SelectedValue == "Marisol") {
tbDescription.Text = customer.ToString();
tbFName.Text = customer.Fname;
tbSocial.Text = customer.SSN;
tbDOB.Text = customer.DOB.ToString();
tbFName1.Text = customer.Fname;
tbMName.Text = customer.Mname;
tbLName.Text = customer.Lname;
tbPrimaryPhone.Text = customer.PrimaryPhone;
tbSecondaryPhone.Text = customer.SecondaryPhone;
tbAdd1.Text = customer.Address;
tbCity.Text = customer.City;
tbZip.Text = customer.Zip;
tbEmail.Text = customer.Email;
tbMonLease.Text = customer.MortLeaseAmt;
tbEmployer.Text = customer.Employer;
tbPosition.Text = customer.Position;
tbHireDate.Text = customer.HireDate.ToString();
tbWorkPhone.Text = customer.WorkPhone;
tbGross.Text = customer.GrossIncome;
}
Debug.WriteLine(tbPosition.Text);
}
When the button is clicked, the page sends a request to the DB, but the textboxes remain blank. I am returning a value from the database, but it's not populating. Here is some code from my front page:
<form id="form1" runat="server">
<asp:DropDownList ID="ddlCustomer" runat="server" DataSourceID="SqlDataSource1" DataTextField="Fname" DataValueField="CustomerID"></asp:DropDownList>
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:APIConnectionString %>" SelectCommand="SELECT [CustomerID], [Fname], [Lname] FROM [Customer] ORDER BY [Fname]"></asp:SqlDataSource><br /><br />
<asp:Button ID="btnChoose" runat="server" Text="Choose Test Case" OnClick="btnChoose_Click" /><br /><br />
Description of Goods and/or Services:<asp:TextBox ID="tbDescription" runat="server"></asp:TextBox><br /><br />
<div>
Membership #:<asp:TextBox ID="tbMembership" runat="server"></asp:TextBox> Ext.: <asp:TextBox ID="tbExt1" runat="server"></asp:TextBox>
First Name:<asp:TextBox ID="tbFName" runat="server"></asp:TextBox><br /> <br /><br />
Soc Sec No.: <asp:TextBox ID="tbSocial" runat="server"></asp:TextBox> Date of Birth:<asp:TextBox ID="tbDOB" runat="server" ></asp:TextBox>
</div><br /> <br />
I'm not sure if the problem is from the code behind or from the front page design. Any help would be appreciate. Thank you.
It looks like your code is checking for a selection in the drop-down list of the name "Marisol" - however, the "Value" field of the drop-down list is configured to use the CustomerID column. So this code populating the fields will never execute.
Maybe you should instead be using ddlCustomer.SelectedValue in the WHERE clause of your query.
I have a webapp that calls on a SQL Query for a list of applications impacted by a project. I want my admins to be able to click edit and add remove applications to this list at will. Currently when they click edit they see every single Application that is Impacted by ANY project as part of the list box even though in the Gridview they only see the Applications Impacted by that specific project. When I hard code the value for the project it works, but I need it to be a variable depending on which project my admins click on to edit.
select
Applications.ApplicationName,
Projects.ProjectName
from ImpactedApplications
inner join Applications
on ImpactedApplications.AppId=Applications.AppId
inner join Projects
on ImpactedApplications.ProjectId=Projects.ProjectId
Where Projects.ProjectId=57 <--This is Hardcoded. I need this to be dynamic.
Adding Code
<asp:TemplateField HeaderText="ImpactedApplications">
<EditItemTemplate>
<asp:ListBox ID="ListBox1" runat="server" DataSourceID="ImpactedApps"
DataTextField="ApplicationName" DataValueField="ProjectName" Width="250px"></asp:ListBox>
<asp:Button ID="Button1" runat="server" Text="Add" />
<asp:Button ID="Button2" runat="server" Text="Remove" />
<asp:ListBox ID="ListBox3" runat="server" DataSourceID="Applications"
DataTextField="ApplicationName" DataValueField="AppId" Width="250px">
</asp:ListBox>
<br />
<asp:SqlDataSource ID="ImpactedApps" runat="server"
ConnectionString="<%$ ConnectionStrings:LandscapeServicesConnectionString %>"
SelectCommand="select Applications.ApplicationName, Projects.ProjectName
from ImpactedApplications
inner join Applications
on ImpactedApplications.AppId=Applications.AppId
inner join Projects
on ImpactedApplications.ProjectId=Projects.ProjectId
where Projects.ProjectName=#Projectname">
<SelectParameters>
<asp:FormParameter DefaultValue="PO Consolidation (EDW)"
FormField="Gridview1 - Column[2] - Project Name" Name="Project Name" />
</SelectParameters>
</asp:SqlDataSource>
Adding Background Code
public partial class Update : System.Web.UI.Page
{
public string query { get; set; }
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["LandscapeServicesConnectionString"].ConnectionString);
DataSet dt = new DataSet();
protected void Page_Load(object sender, EventArgs e)
{
con.Open();
}
protected void GridView1_RowEditing(object sender, GridViewEditEventArgs e)
{
GridView1.EditIndex = e.NewEditIndex;
}
}
Create a parameterized query:
select
Applications.ApplicationName,
Projects.ProjectName
from ImpactedApplications
inner join Applications
on ImpactedApplications.AppId=Applications.AppId
inner join Projects
on ImpactedApplications.ProjectId=Projects.ProjectId
where Projects.ProjectId=#projectId
Then when you create your SqlCommand add a parameter and give it the value from your form:
cmd.Parameters.AddWithValue("#projectId",projectId);
This question to related to a similar Data list question I posted some days ago. I have a datalist which displays Categories, and then documents within categories. What needs to happen is that documents under each category gets displayed in the order based on some numbers in file names. Documents are in format like '001-filename.pdf', '002-filename.pdf' ... '00x-filename.pdf'. I can use the first dash as some kind of 'split' function then grab the numbers like '001' etc to make the sorting to work. I think this could be done on either itemdatabound or in the sql syntax. I am posting the relevant code here. Any idea as to how I can make this to work? It is possible that there could be more than one document with shared number prefix: '001-filename.pdf', '001-filenameversion2.pdf' etc. Thanks!
ASPX:
<asp:DataList ID="DataList1" runat="server" RepeatDirection="Vertical" DataKeyField="docid"
EnableViewState="True" OnItemDataBound="DataList1_ItemDataBound">
<ItemTemplate>
<table cellpadding="0" cellspacing="0" id="tbl_data">
<tr runat="server" id="tr_category">
<td>
<asp:Label ID="lblHeader" runat="server" Font-Bold="True" Text='<%# Eval("categoryname") %>'
Font-Underline="True"></asp:Label>
<asp:Label runat="server" ID="lbl_cb_all">Select All
<asp:CheckBox runat="server" OnCheckedChanged="CheckAllChanged" AutoPostBack="true"
ID="cb_selectall" />
</asp:Label>
<asp:HiddenField ID="HiddenCatID" runat="server" Value='<%# Eval("CatID") %>' />
<asp:HiddenField ID="HiddenDocID" runat="server" Value='<%# Eval("docid") %>' />
</td>
</tr>
<tr runat="server" id="tr_data">
<td>
<asp:CheckBox runat="server" ID="cb_docid" Value='<%# Eval("docid") %>' OnCheckedChanged="displayselectedinit"
AutoPostBack="true" />
<asp:HyperLink ID="hpl_docfileencr" Text='<%# Eval("docfileencr") %>' NavigateUrl='<%# "~/PDFEncr/" + DataBinder.Eval(Container.DataItem, "docfileencr") %>'
Target="_blank" runat="server" />
<br />
</td>
</tr>
</table>
</ItemTemplate>
</asp:DataList>
C# CodeBehind:
sqlsyntax = #"SELECT dbo.projectsdocuments.docfileencr,dbo.categories.catid, dbo.categories.categoryname, dbo.projectsdocuments.docid
FROM dbo.Projects INNER JOIN dbo.projectsdocuments ON (dbo.Projects.projectid = dbo.projectsdocuments.projectid)
INNER JOIN dbo.categories ON (dbo.projectsdocuments.categoryid = dbo.categories.catid)
WHERE Projects.projectid = " + projectid + " ORDER BY dbo.categories.sortorder ASC";
protected void DataList1_ItemDataBound(Object sender, DataListItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
var row = (DataRowView)e.Item.DataItem;
var view = row.DataView;
var lastRow = e.Item.ItemIndex == 0 ? null : view[e.Item.ItemIndex - 1];
var tr_category = (System.Web.UI.HtmlControls.HtmlTableRow)e.Item.FindControl("tr_category");
var sameCategory = lastRow != null && (int)row["catid"] == (int)lastRow["catid"];
tr_category.Visible = !sameCategory;
}
}
Change your ORDER BY to include both columns.
SELECT
dbo.projectsdocuments.docfileencr,
dbo.categories.catid,
dbo.categories.categoryname,
dbo.projectsdocuments.docid
FROM dbo.Projects
INNER JOIN dbo.projectsdocuments
ON (dbo.Projects.projectid = dbo.projectsdocuments.projectid)
INNER JOIN dbo.categories
ON (dbo.projectsdocuments.categoryid = dbo.categories.catid)
WHERE Projects.projectid = " + projectid + "
ORDER BY dbo.categories.sortorder, dbo.projectsdocuments.docfileencr
The order by precedence is left to right, the default is "ASCENDING" but you can change a specific column sort by adding "ASC or DESC" directly after it.
** IMPORTANT NOTE **
Your code is susceptible to SQL Injection because your doing string concatenation. If this is a concern to you, change the SQL statement to use a named parameter that you assign using a command parameter (see example below).
Step 1: Change the inline string parameter, to a named parameter "#projectid".
SELECT
dbo.projectsdocuments.docfileencr,
dbo.categories.catid,
dbo.categories.categoryname,
dbo.projectsdocuments.docid
FROM dbo.Projects
INNER JOIN dbo.projectsdocuments
ON (dbo.Projects.projectid = dbo.projectsdocuments.projectid)
INNER JOIN dbo.categories
ON (dbo.projectsdocuments.categoryid = dbo.categories.catid)
WHERE Projects.projectid = #projectid
ORDER BY dbo.categories.sortorder, dbo.projectsdocuments.docfileencr
Step 2: Assign the parameter inline (example code)
using(SqlConnection conn = new SqlConnection(connString))
{
conn.Open();
SqlCommand command = new SqlCommand(sql, conn);
command.CommandType = CommandType.Text;
// Assign the value projectid to the parameter #projectid
command.Parameters.Add(new SqlParameter("#projectid", projectid));
// Execute The Command (fill dataset, create datareader, etc...)
SqlDataReader reader = command.ExecuteReader();
}