I am working on displaying a students timetable based on possible Module choices. Each time a check box is selected I want to pass through the value selected "ModuleId" to use in a SELECT query to display the timetable for all modules selected. So if a user selects 3 check boxes the 'ModuleId' from each row selected will be passed into the SELECT query.
I don't know how to store each selected "ModuleId" and add it into my select query.
Below is how I retrieve the checked value:
<asp:TemplateField>
<ItemStyle HorizontalAlign="Center" Width="40px"></ItemStyle>
<ItemTemplate>
<asp:CheckBox ID="chkRow" runat="server" ToolTip='<%# Eval("ModuleId") %>' OnCheckedChanged="module_Changed" />
</ItemTemplate>
<asp:TemplateField>
Below is my method to display the value in a label (just for testing purposes):
protected void module_Changed(object sender, EventArgs e)
{
// Retrieve the check box ModuleId value to add to my SELECT query
string moduleid = ((CheckBox)sender).ToolTip;
}
Below is my method which contains the select query to display the timetable:
public String[] getModulesAtCurrentSlot(int timeslotInt, String moduleID, String Day)
{
List<String> modulesList = new List<string>();
if (conn.State.ToString() == "Closed")
{
conn.Open();
}
SqlCommand newCmd = conn.CreateCommand();
newCmd.Connection = conn;
newCmd.CommandType = CommandType.Text;
newCmd.CommandText = "SELECT DISTINCT Module.ModuleCode,ClassType.ClassTypeName,Convert(time,Class.StartTime), Convert(time,Class.EndTime),Building.BuildingName,RoomCode.RoomCode,Class.Color" +
" FROM Class INNER JOIN Module ON Class.ModuleId = Module.ModuleId INNER JOIN RoomCode ON Class.RoomCodeId = RoomCode.RoomcodeId INNER JOIN Building ON RoomCode.BuildingId = Building.BuildingId INNER JOIN Days ON Class.DayId = Days.DayID INNER JOIN ClassType ON Class.ClassTypeId = ClassType.ClassTypeId WHERE " +
" Module.ModuleId = " + moduleID + " AND Convert(Date,StartTime) = '" + Day + "' AND " + timeslotInt.ToString() + " BETWEEN ClassScheduleStartTimeId and ClassScheduleEndTimeId";
SqlDataReader dr = newCmd.ExecuteReader();
while (dr.Read())
{
String current = "<div class='slot' " + (!dr.IsDBNull(6) ? "style=\"background-color: " + dr.GetString(6) + ";\"" : "") + ">";
current += "<div class='line1'>" + dr.GetString(0) + " " + dr.GetString(1) + "</div>";// +"<br />";
current += "<div class='line2'>" + dr.GetTimeSpan(2).ToString().TrimEnd('0').TrimEnd('0').TrimEnd(':') + " - " + dr.GetTimeSpan(3).ToString().TrimEnd('0').TrimEnd('0').TrimEnd(':') + "</div>";// +"<br />";
current += "<div class='line3'>" + dr.GetString(4) + " " + dr.GetString(5) + "</div>";
current += "</div>";
modulesList.Add(current);
}
conn.Close();
return modulesList.ToArray();
}
On a previous page where the timetable is only displaying data for one ModuleId I've used the below query string to pass through the value.
String module_ID = "2";
if (Request.QueryString["module"] != null)
{
module_ID = Request.QueryString["module"];
}
else
{
Response.Write("Missing ?module=XX from url :(");
Response.End();// EndRequest;
}
DBAccess.cs screenshot:
Error screenshot:
If I understand correctly, you could have a session variable that contains a List of strings which holds all of the selected moduleID's
You could then use module_Changed event to add or remove moduleIDs from this List and then call getModulesAtCurrentSlot in a loop for each moduleid in the list and concatenate the returned string[]s into one longer string[] or List which you then display.
there may be some errors in the code below as I'm just doing it from memory but it should give you an idea!
protected void module_Changed(object sender, EventArgs e)
{
List<string> lst;
if( Session["lst"]!=null)
lst = (List<string>)Session["lst"];
else
Session.Add("lst", new List<string>());
// Retrieve the check box ModuleId value to add to my SELECT query
string moduleid = ((CheckBox)sender).ToolTip;
// add your own code to check if checkbox is checked or unchecked to see if you need to add or remove the ID from the list
// to add
if(lst.Contains(moduleid) == false)
lst.Add(moduleid);
// to remove - add your own code
List<string> lstResult = new List<string>();
foreach(var moduleID in lst)
{
lstResult.Add(getModulesAtCurrentSlot(timeslotInt, moduleID, Day));
}
// do something to display lstResult
// e.g. drag a Gridview control on your aspx page and bind the results list to it - this is just to give you a rough idea but you'll need to play around with it to get it to work as you want, and hopefully learn something in the process ;)
Gridview1.DataSource = lstResult;
Gridview1.Databind();
}
Related
I am working on displaying a students timetable based on possible Module choices. (See Screenshot) Currently I am displaying all available modules in a gridview which the student can select by using check boxes. I have already created the insert query to insert their selection to the database. (2)
However, each time a check box is selected I want to retrieve the 'ModuleId' to add to a SELECT query which displays a timetable of their selected modules. (1)
So if a user selects 3 check boxes the 'ModuleId' from each row selected will be passed into the SELECT query.
Below is my method which enables the timetable for specific a ModuleId to be displayed:
public String[] getModulesAtCurrentSlot(int timeslotInt, String moduleID, String Day)
{
List<String> modulesList = new List<string>();
if (conn.State.ToString() == "Closed")
{
conn.Open();
}
SqlCommand newCmd = conn.CreateCommand();
newCmd.Connection = conn;
newCmd.CommandType = CommandType.Text;
newCmd.CommandText = "SELECT DISTINCT Module.ModuleCode,ClassType.ClassTypeName,Convert(time,Class.StartTime), Convert(time,Class.EndTime),Building.BuildingName,RoomCode.RoomCode,Class.Color" +
" FROM Class INNER JOIN Module ON Class.ModuleId = Module.ModuleId INNER JOIN RoomCode ON Class.RoomCodeId = RoomCode.RoomcodeId INNER JOIN Building ON RoomCode.BuildingId = Building.BuildingId INNER JOIN Days ON Class.DayId = Days.DayID INNER JOIN ClassType ON Class.ClassTypeId = ClassType.ClassTypeId WHERE " +
" Module.ModuleId = " + moduleID + " AND Convert(Date,StartTime) = '" + Day + "' AND " + timeslotInt.ToString() + " BETWEEN ClassScheduleStartTimeId and ClassScheduleEndTimeId";
SqlDataReader dr = newCmd.ExecuteReader();
while (dr.Read())
{
String current = "<div class='slot' " + (!dr.IsDBNull(6) ? "style=\"background-color: " + dr.GetString(6) + ";\"" : "") + ">";
current += "<div class='line1'>" + dr.GetString(0) + " " + dr.GetString(1) + "</div>";// +"<br />";
current += "<div class='line2'>" + dr.GetTimeSpan(2).ToString().TrimEnd('0').TrimEnd('0').TrimEnd(':') + " - " + dr.GetTimeSpan(3).ToString().TrimEnd('0').TrimEnd('0').TrimEnd(':') + "</div>";// +"<br />";
current += "<div class='line3'>" + dr.GetString(4) + " " + dr.GetString(5) + "</div>";
current += "</div>";
modulesList.Add(current);
}
conn.Close();
return modulesList.ToArray();
}
How would I pass all selected values (ModuleId) from the checkboxes to be used in my above select query as previously for displaying just one module I used
' Module.ModuleId = " + moduleID ' ?
To complete what you are trying to do efficiently and without big foreach loops you need to change the whole way your user inputs data in to the gridview.
I believe that you should be utilising the GridViews OnRowUpdating Event, When a row is updated, using this event you already have context of which row has changed. e.RowIndex - Gets the index of the row being updated
Utilising this event will require a bit of a redesign of your gridview fields, You will need to add a EditItemTemplate tag in each TemplateField Add a CommandFieldand using OnRowUpdating re-write your update event. Its to much information to post in a answer, This information should help you get started on using the GridView events to their full potential.
On a side note you should use paramerterized queries in your sql.
EDIT
Based on your clarification that you need to retrieve the moduleid for each checkbox, I am going to make a few assumptions so it might not work without some tweaks.
To start with try this:
<asp:TemplateField>
<ItemStyle HorizontalAlign="Center" Width="40px"></ItemStyle>
<ItemTemplate>
<asp:CheckBox ID="chkRow" runat="server" ToolTip='<%# Eval("ModuleId") %>' OnCheckedChanged="module_Changed" />
</ItemTemplate>
Using '<%# Eval("ModuleId") %>' Will populate the tooltip for the checkbox with the ModuleID value during the GridView.DataBind() function. Iam making the assumption that the column name is exactly "ModuleId"
Then in the code behind you can read the tooltip value of the checkbox like this:
protected void module_Changed(object sender, EventArgs e)
{
// Retrieve the check box ModuleId value to add to SELECT query
string moduleid = ((CheckBox)sender).ToolTip;
}
Now that when the gridview loads all the checkboxes have a tooltip that is populated with the ModuleID you can easily know which box is for which module by checking the tooltip.
I have a rather irritating and silly problem. I have a checkbox list on a asp page that I populate from a database. I am able to populate it, the problem lies when I do a specific check that checks if the users are active or not, it displays only the ones that are active but then leaves huge blanks in my control of where the original not active users were displayed.
I have pictures of before and after I implement that specific if statement:
here is the code for populating and checking:
this.AddMultipleUsers.Items.Clear();
foreach (GetAllLoginUsersResult result in from a in this.db.GetAllLoginUsers(null)
orderby a.FirstName
select a)
{
ListItem item = new ListItem();
string str = Membership.GetUser(result.UserId).ToString();
item.Text = result.FirstName.Trim() + " " + result.Surname.Trim() + " (" + str + ")";
if (!result.IsApproved)
{
item.Text = item.Text + " (Not Active)";
//item.Attributes.Add("style", "display:none;"); before
}
item.Value = result.UserId.ToString();
this.AddMultipleUsers.Items.Add(item);
}
in the first image, the checkboxlist is fully populated. Before link to code^
in the second after I un-comment this line //item.Attributes.Add("style", "display:none;");
then checkboxlist is the same size as the first image but, there is large spaces between
the users that are active, when you scroll down you see them randomly.
I want to remove the blank items within the checkbox list and make the other valid entries to be moved up like a normally populated checkbox list
Thank you
simply add a where condition to your select statement:
this.AddMultipleUsers.Items.Clear();
foreach (GetAllLoginUsersResult result in from a in this.db.GetAllLoginUsers(null)
orderby a.FirstName
where a.IsApproved==true
select a)
{
ListItem item = new ListItem();
string str = Membership.GetUser(result.UserId).ToString();
item.Text = result.FirstName.Trim() + " " + result.Surname.Trim() + " (" + str + ")";
item.Value = result.UserId.ToString();
this.AddMultipleUsers.Items.Add(item);
}
now you are only cycling through the active users, and no longer need to hide the inactive ones.
SqlDataReader myReader1 = null;
SqlCommand myCommand1 = new SqlCommand("SELECT Standard_Note_Code, COUNT(Standard_Note_Code) as Count FROM [Excel_table] where Standard_Note_Creator_Name = '" + ddlrep.Text + "' and (Std_Note_Date_Entered >= '" + datefrom + "' and Std_Note_Date_Entered <= '" + dateto + "') group by Standard_Note_Code", myConnection);
myReader1 = myCommand1.ExecuteReader();
myReader1.Read();
gvsummary.Visible = true;
if (myReader1.HasRows)
{
gvsummary.DataSource = myReader1;
gvsummary.DataBind();
}
else
{
myReader1.Close();
//myConnection.Close();
//Label2.Text = "No Records Exist";
}
myReader1.Close();
Remove myReader1.Read();, after ExecuteReader. That line causes the grid to start reading from the 2nd position.
Everything looks correct to me, except I don't think you should be calling
myReader1.Read();
before you bind to the GridView. I think if you remove that line it will fix your problem.
Don't call myReader1.Read(); if you're binding as a data source.
I am coding "List all Product" page in asp.net. I did the connection from the DB to ViewList. Now I have to make the products clickable. What I have coded so far in the asp part is , as it follows:
<div class="image">
<asp:HyperLink ID="HyperLinkSaleDesign" runat="server" NavigateUrl='<%# Eval("ID" , "~/EN/ViewTemplate.aspx?id={0}") %>'>
<asp:Image ID="ImageSaleDesign" runat="server" Width="247" Height="150" ImageUrl='<%# Eval("thumb") %>' />
</asp:HyperLink>
</div>
The navigation URL works and I can see the selected "?id={0}".
However I cannot pass the data correctly , so the SQL query on the next page does not work.
I am not sure how to pass this value to the Select statement. Here is what I have done so far:
String IDquery = ("QueryStringParameter[ID]"); // doesn't work
try
{
string ConnectionString = WebConfigurationManager.ConnectionStrings["Twebconfig"].ConnectionString;
SqlConnection viewTemplate = new SqlConnection(ConnectionString);
SqlDataAdapter viewTemplateSet = new SqlDataAdapter("SELECT " +
" * FROM saleDesigns WHERE ID = #IDquery", viewTemplate); // doesn't seem to see the variable
Data Binding - etc. etc. etc
}
catch (Exception err)
{
mylabel.Text = "Invalid " + err.Message;
}
I am open to any suggestions.
Thank you.
I'm a bit confused by your code, but it looks like you just need to retrieve the id from QueryString and build a SQL query with it, right?
Is this what you're trying to do?:
int id = int.Parse(Request.QueryString["id"]);
You can put the query together using the ID from QueryString, you can do something like this:
//just an example - should be parameterized to avoid injection
string query = String.Format("SELECT ID, Col1, Col2 FROM Table1 WHERE ID={0}", Request.QueryString["ID"]);
This is the way it works for me:
int v = 0;
try
{
int v = int.Parse(Request.QueryString["id"]);
}
catch (Exception e)
{}
if (v > 0)
{
try
{
string ConnectionString = WebConfigurationManager.ConnectionStrings["connstring"].ConnectionString;
SqlConnection conn = new SqlConnection(ConnectionString);//explisionremoteEntities
string query = String.Format("SELECT * FROM table WHERE ID={0}", Request.QueryString["ID"]);
SqlDataAdapter viewTemplateSet = new SqlDataAdapter(query, conn);
}
catch
{
//code in here
}
}
I have used a rich textbox control,ckeditor in my case,When any formatting is done to the text the formatted text is populated in the datagrid.But I want to extract only the plain text in the grid and trim the length of data to 80 characters while populating.
The query for updating the answer is as follows
protected void btnUpdate_Click(object sender, EventArgs e)
{
if (txtEditorAnswer.Text.Trim() != string.Empty)
{
int intIsUpdated = 0;
string strUpdateQuery = "UPDATE M_QA SET ANSWER = '" + txtEditorAnswer.Text.Trim().Replace("'", "''")
+ "', UPDATED_ON = getDate(), UPDATED_BY = '" + this.Session["UserId"].ToString()
+ "' WHERE PK_ID = " + _currentQuestionId + " AND IS_ACTIVE = 1";
and the query for populating data in the grid is as follows:
protected void LoadQA(int intQuestionId)
{
string strSelectQuery = "SELECT REPLACE(TITLE, '\n', '<br />') TITLE, REPLACE(DESCRIPTION, '\n', '<br />') DESCRIPTION, "
+ "ANSWER, FK_OWNER_ID, CREATED_ON FROM M_QA WHERE PK_ID = "
+ intQuestionId + " AND IS_ACTIVE = 1";
can plz some buddy help me!!
Use the HTML agility pack, parse your query result on ItemDataBound event then select only the text() nodes to display