ASP repeater sorting ItemDataBound - asp.net

I'm having a bit of trouble with ASP Repeaters and trying to sort the data.
So on Page_Load I obtain the datasource as below...
Protected Overloads Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
If Not (Page.IsPostBack) Then
'No need to re-load Occasion because it's done in the PreLoad event
Me.Header.Title = "OCP - " + Occasion.Checklist.name
pnlStatistics.Visible = Not (Occasion.isClosed)
pnlClose.Visible = SecurityHelper.HasRole(SecurityMatchOption.AtLeast, SecurityRole.Manager, _relevantTeam) And Not (Occasion.isClosed)
'initially assume checklist can be closed. any un-signed off task in the item_databound event will disable it.
btnClose.Enabled = True
'Fix Issue 63: rptTask.DataSource = _db.vw_tasklists.Where(Function(o) o.occasionId = Occasion.id).ToList()
rptTask.DataSource = _db.vw_tasklists.Where(Function(o) o.occasionId = Occasion.id).OrderBy(Function(t) t.taskDueDate).ThenBy(Function(t) t.taskDueTime)
However within ItemDataBound we recalculate the task duedate.
Private Sub rptTask_ItemDataBound(sender As Object, e As RepeaterItemEventArgs) Handles rptTask.ItemDataBound
' Get the data relating to this task 'row'
Dim t = CType(e.Item.DataItem, vw_tasklist)
If e.Item.ItemType = ListItemType.Header Then
Dim thDueDate = CType(e.Item.FindControl("thDueDate"), HtmlTableCell)
thDueDate.Visible = Not (Occasion.isClosed)
End If
'securable buttons
If e.Item.ItemType = ListItemType.Item Or e.Item.ItemType = ListItemType.AlternatingItem Then
' Dynamically create a span element named TASKnnnn, which will be referenced from
' 'child page' links back to this page in order to vertically reposition at the selected task
Dim span = New HtmlGenericControl("span")
span.ID = "TASK" & t.taskId
span.ClientIDMode = ClientIDMode.Static ' prevent ASP.NET element ID mangling
e.Item.FindControl("lblTaskName").Parent.Controls.AddAt(0, span) ' hook it into the repeater row
Dim btnSignoff = CType(e.Item.FindControl("btnSignOff"), Button)
Dim btnComment = CType(e.Item.FindControl("btnComment"), Button)
Dim btnAmend = CType(e.Item.FindControl("btnAmend"), Button)
Dim btnView = CType(e.Item.FindControl("btnView"), Button)
Dim lblSoTime = CType(e.Item.FindControl("lblSOTime"), Label)
Dim lblDueDate = CType(e.Item.FindControl("lblDueDate"), Label)
Dim lblTaskId = CType(e.Item.FindControl("lblTaskId"), Label)
Dim lblTaskName = CType(e.Item.FindControl("lblTaskName"), Label)
lblTaskId.Text = CType(t.taskId, String)
lblTaskName.Text = t.taskName
Dim time = (If(t.taskDueTime Is Nothing, New TimeSpan(0, 23, 59, 59), TimeSpan.Parse(t.taskDueTime)))
Dim dueDateTime As DateTime = (Occasion.started.Date + time)
'Setup up due DateTime for Daily Tasks
Select Case DirectCast(t.taskDayTypeId, helpers.Constants.enDayType)
Case helpers.Constants.enDayType.Daily
lblDueDate.Text = dueDateTime.ToString("dd/MM/yyyy HH:mm")
Exit Select
Case Else
'Calculate the actual due date for non-daily tasks
Dim calculator = New Calculator()
Dim calId = t.taskCalendarId
Dim taskMonthDay = "1"
If Not t.taskMonthDayId Is Nothing Then
taskMonthDay = CType(t.taskMonthDayId, String)
End If
Dim monthDay = _db.MonthDays.First(Function(m) m.id = CInt(taskMonthDay))
Dim calendar As Model.Calendar = Nothing
If Not calId is Nothing Then
calendar = _db.Calendars.First(Function(x) calId.Value = x.id)
End If
Dim potDate = calculator.GetActualDueDate(dueDateTime, monthDay.monthDay, t, calendar)
dueDateTime = (potDate.Date + time)
lblDueDate.Text = dueDateTime.ToString("dd/MM/yyyy HH:mm")
Exit Select
End Select
Therefore once the data is displayed in the repeater the sorting is wrong. I need to be able to sort the data after the due date re-calculation. How is this possible?
Thanks

You can to move the ItemDataBound logic up into the original query:
rptTask.DataSource = _db.vw_tasklists.
Where(Function(o) o.occasionId = Occasion.id).
Select(
Function(r)
'Fill in the logic here so the DueProperty has your real Due Date
New With {.Row = r, .DueDate = r.TaskDueDate + r.TaskDueTime}
End Function
OrderBy(Function(t) t.DueDate). ' Now we only need one OrderBy (the time is already included).
Select(Function(r) r.Row) 'But we do want to select back to the original record for the databinding
'And the ToList() was probably NEVER needed or helpful in this situation
Moreover, since this looks like linq-to-sql I might break that up a bit, so we cleanly separate what we expect to execute on the database from what we expect to execute on the web server:
'This runs on the databsae
Dim sqlData = _db.vw_tasklists.
Where(Function(o) o.occasionId = Occasion.id)
'This runs on the web server
rptTask.DataSource = sqlData.
Select(
Function(r)
'Fill in the logic here so the DueProperty has your real Due Date
New With {.Row = r, .DueDate = r.TaskDueDate + r.TaskDueTime}
End Function
OrderBy(Function(t) t.DueDate). ' Now we only need one OrderBy (the time is already included).
Select(Function(r) r.Row) 'But we do want to select back to the original record for the databinding
'And the ToList() was probably NEVER needed or helpful in this situation
Of course, you'll get the best results if you start putting information into the database such that you can effectively sort your data correctly there at the outset.

Related

How to find the value of a dropdownlist using FindControl?

I am working on a website with VB.NET and ASP.NET. I currently have recurring DropDownLists for the user to provide input.
The design is recurring. These DropDownLists get their values from a database table, Everything with the Web interface is working except for writing these recurring values to the database - that is just to give you some background.
I have set the ID's of each DropDownList like so:
FrequencyList.ID = String.Concat("FreqList", DBReader(0))
That is in a loop while reading the DatabaseReader.
This is what I'm having issues with (please note I simplified the code down to make it easier to read:
Dim i As Integer
DBCommand = New SqlCommand()
DBCommand.Connection = DBConnection
DBCommand.CommandType = Data.CommandType.StoredProcedure
DBCommand.CommandText = "StoredProcedureName"
DBConnection.Open()
For i = 1 To AspectTableLength
Dim ParamFrequencyID As SqlParameter = DBCommand.Parameters.Add("#nFrequencyID", SqlDbType.Int)
ParamFrequencyID.Value = FindControl("FreqList" & Convert.ToString(i))
ParamFrequencyID.Direction = ParameterDirection.Input
Next
The FindControl("FreqList" & Convert.ToString(i)) variable is incorrect because it does not access the value - and adding .SelectedItem.Value does not work.
I got help from a developer.
Dim MyControls As ControlCollection = Panel.Controls
Dim Number As Integer 'this is the same as "DBReader(0)"
For Each MyControl As Control In MyControls
If MyControl.ID Is Nothing Then
Else
If MyControl.ID.StartsWith("Span") Then
Number = Replace(MyControl.ID, "Span", "")
Dim Freq As DropDownList = PanelMain.FindControl(“FreqList” & Number)
Dim ParamFrequencyID As SqlParameter = DBCommand.Parameters.Add("#nFrequencyID", SqlDbType.Int)
ParamFrequencyID.Value = Freq.SelectedIndex
ParamFrequencyID.Direction = ParameterDirection.Input
DBCommand.ExecuteNonQuery()
DBCommand.Parameters.Clear()
End If
End If
Next
DBConnection.Close()

Checkbox list keep disabled

Trying to use checkbox lists in (calendar booking system). The checkbox should be disabled and red if there are any data in the database against the date and hour. This all work perfectly here is the code. Using vb.net
OK i found a way how to clear the checkboxes
Dim i As Integer
Dim chboxItem As ListItem
For Each chboxItem In CheckBoxListMon.Items
i += 1
If (i Mod 1 = 0) Then
chboxItem.Enabled = True
End If
Next
Protected Sub Page_LoadComplete(sender As Object, e As EventArgs) Handles Me.LoadComplete
Try
strQuery = "SELECT BookingDate, checkBoxItem, BookRegUserID,Booked FROM bookings INNER JOIN checkboxitems where checkBoxItem = BookingTime"
MySQLCmd = New MySqlCommand(strQuery, dbCon)
dbCon.Open()
DR = MySQLCmd.ExecuteReader
While DR.Read
bookDate = DR.Item("BookingDate")
bookTime = DR.Item("checkBoxItem")
bookRegID = DR.Item("BookRegUserID")
booked = DR.Item("Booked")
Dim test As String = bookTime.ToString()
Select Case True
Case bookDate = lblMonday.Text And CheckBoxListMon.Items.FindByValue(test) IsNot Nothing
CheckBoxListMon.Items.FindByValue(bookTime).Enabled = False
CheckBoxListMon.Items.FindByValue(bookTime).Attributes.Add("Style", "color: red;")
End Select
End While
DR.Close()
dbCon.Close()
Catch ex As Exception
End Try
End Sub
When the page load it would not change the ones from the database. But when i reload the page it will actually work perfect.
Where can i put the check just to be sure that they are already in the memory.
Any help will be much appreciated. Thanks all.
Petr
You need to refresh the data when another week is selected because you are using the same controls for each week. You should be able to do this in whatever control you are using to toggle through the weeks.
Page_LoadComplete can only be expedted to fire each time a page has completed loading, that is why your controls work when going to another page and back.

Changing DropDown Selected Item Based on Selected Value (ASP.NET)

I have a dropdown list on my page (ddlProgram) which is populated via a database query like so:
Using dbContext as IRFEntities = New IRFEntities
Dim getPrograms = (From p in dbContext.IRF_Program _
Order By p.name _
Select p)
ddlProgram.DataSource = getPrograms
ddlProgram.DataTextField = "name"
ddlProgram.DataValueField = "id"
ddl.Program.DataBind()
End Using
So, for example, one might have a DataTextField of "Education" and an ID of "221".
Now, I prepopulate the form with information about the individual visiting the site (if available) - including the dropdown list like so:
If getProspect IsNot Nothing Then
If getProspect.user_id Is Nothing Then
ddlProgram.SelectedValue = getProspect.Program
End If
End If
The Program property contains a number that matches the ID of a Program. So, for example, this individual might have a Program of "221" which would match the "221" of Education mentioned above.
Currently the application successfully sets the SelectedValue to "221" for the DropDownList (ddlProgram), but the SelectedItem of the DDL remains the same (e.g., if it is initially "History" with an ID of "1" after the prepopulation it is "History" with an ID of "221").
What I'm trying to make happen is that the SelectedItem is updated to item which corresponds with the SelectedValue. So, in the end, if the individual has "221" for "Education" selected when the form is prepopulated they would see Education as the selected item and the selected value would be set correctly, whereas right now the form is showing the wrong SelectedItem but has the right SelectedValue behind the scenes.
Here is a more complete idea of the code flow from the Page_Load event:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Page.IsPostBack = False Then
' If prospect is coming from unique url
Dim prospect_url As String = Page.RouteData.Values("value")
' Save prospect_url into session variable
Session("prospect_url") = prospect_url
Using dbContext As IRFEntities = New IRFEntities
' Prepopulate the programs dropdown.
Dim getPrograms = (From p In dbContext.IRF_Program _
Order By p.name _
Select p)
ddlProgram.DataSource = getPrograms
ddlProgram.DataTextField = "name"
ddlProgram.DataValueField = "id"
ddlProgram.DataBind()
End Using
Using dbContext As IRFEntities = New IRFEntities
' Prepopulate the states dropdown.
Dim getStates = (From p In dbContext.IRF_States _
Order By p.name _
Select p)
ddlState.DataSource = getStates
ddlState.DataTextField = "name"
ddlState.DataValueField = "id"
ddlState.DataBind()
End Using
Using dbContext As IRFEntities = New IRFEntities
' Grab info. about prospect based on unique url.
Dim getProspect = (From p In dbContext.IRF_Prospects _
Where p.url = prospect_url _
Select p).FirstOrDefault
' If they have a record...
If getProspect IsNot Nothing Then
If getProspect.user_id Is Nothing Then
' Prepopulate the form with their information.
' These must have a value, so we need to make sure that no column is null in the database.
ddlProgram.SelectedValue = getProspect.program
txtFirst.Text = getProspect.first_name
txtLast.Text = getProspect.last_name
txtAddress.Text = getProspect.address
txtCity.Text = getProspect.city
ddlState.SelectedValue = getProspect.state
txtZip.Text = getProspect.zip
txtPhone.Text = getProspect.phone
txtEmail.Text = getProspect.email_address
txtYearEnrolling.Text = getProspect.enrolling_in
Else
' Redirect them to login.
Response.Redirect("login.aspx")
End If
End If
End Using
End If
End Sub
What you're doing looks like it should work. If you put a breakpoint after the setting of the value and check the SelectedItem text and value, do they appear as expected or mismatched?
Use the Immediate Window to check:
ddlProgram.SelectedItem.Text
ddlProgram.SelectedItem.Value
If they appear the same then I would presume the binding code is being refired and the list is being regenerated with the first item being selected.
To check this put a break point on the binding code and see if it is fired more than once and correct the order of the methods appropriately.
ADDED:
If it works on your local environment it should work when published, if the code is the same? Looking at your code, I'd start by seperating out some of the databinding code into seperate methods rather than have everything in Page_Load, one becuase it's good practice and two because it will make debugging easier. Further than that I'm not sure what else to suggest.

Attempting to create shopping cart remove button

Note: This code actually codes from a tutorial book I'm reading at the moment, so you can imagine this is frustrating me greatly! I'm building a basic shopping cart, using VB.NET 4, Visual Studio 2010 and MS SQL Server R2 2008. The code below is supposed to remove items from the cart, by reading a session variable, editing it to remove the appropriate ProductID and return the amending string to the session variable. It is then supposed to rebind the data to the gridview (gvCart) to refresh the data...but it seems here there is an error.
Every time I build the site in Visual Studio, it validates fine. But every time I run the site, and attempt to use the remove button it gives me the error:
Incorrect syntax near ')'.
with the IDE pointing me toward the final parenthesis.
I have been pulling my hair out at this for a good 4 hours now, any advice appreciated!
Protected Sub gvCart_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles gvCart.SelectedIndexChanged
'This method is hooked to the Remove button & is removing items from the cart
Dim strProductId As String = gvCart.SelectedRow.Cells(1).Text
If Session("Cart") IsNot Nothing Then
'Remove selected ProductID from Session string and retrieve session string
Dim strCart As String = Session("Cart").ToString()
Dim arIDs As String() = strCart.Split(",")
'Iterate through ID's in the 'Cart' array and rebuild the string leaving out the selected ID
strCart = String.Empty
For Each str As String In arIDs
'use Trim to remove leading and trailing spaces
If str.Trim() <> strProductId.Trim() Then
strCart += str + ", "
End If
Next
'Remove trailing space and comma
If strCart.Length > 1 Then
strCart = strCart.Trim()
strCart = strCart.Substring(0, strCart.Length - 1)
End If
'Put back into session var
Session("Cart") = strCart
'Rebind gvCart, which forces the sqldatasource to requery
gvCart.DataBind()
End If
End Sub
[EDIT]
I am also including the code that runs for the event sqlCart_Selecting for completion sake:
Protected Sub sqlCart_Selecting(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.SqlDataSourceSelectingEventArgs) Handles sqlCart.Selecting
Trace.Warn("sqlCart_Selecting") 'aids debugging
Dim strCart As String = String.Empty
If Session("Cart") IsNot Nothing Then
strCart = Session("Cart").ToString
e.Command.CommandText &= " WHERE product.ProductID IN (" + strCart + ") AND culture.CultureID = 'en'"
Else
e.Cancel = True
End If
End Sub
[EDIT]
Also including the SQL query used by the gridview 'gvCart' and the code for displaying the carts contents on another page
<asp:SqlDataSource ID="sqlCart" runat="server" ConnectionString="<%$ ConnectionStrings:AdventureWorksConnectionString %>" SelectCommand="SELECT product.ProductID, product.Name, product.ProductNumber, product.Color, subcat.Name AS SubcategoryName, cat.Name AS CategoryName, description.Description FROM Production.Product product JOIN Production.ProductSubcategory subcat ON product.ProductSubcategoryID = subcat.ProductSubcategoryID JOIN Production.ProductCategory cat ON subcat.ProductCategoryID = cat.ProductCategoryID JOIN Production.ProductModel model on product.ProductModelID = model.ProductModelID JOIN Production.ProductModelProductDescriptionCulture culture ON model.ProductModelID = culture.ProductModelID JOIN Production.ProductDescription description ON culture.ProductDescriptionID = description.ProductDescriptionID"></asp:SqlDataSource>
Protected Sub btnAddToCart_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnAddToCart.Click
'The contents of the cart will be saved in a Session object as a string of coma-delimited values of ProductID's
Dim strCart As String = String.Empty
Dim strProductID As String = gvProducts.SelectedDataKey.Value.ToString()
If Session("Cart") Is Nothing Then
strCart = strProductID
Else
strCart = Session("Cart").ToString() + ", " + strProductID
End If
Session("Cart") = strCart
lblCart.Text = strCart
End Sub
I will take a shot here, since you are not showing us everything (the SQL query for instance).
But it feels like the SQL query is using IN clause. And it appears to be failing when the cart goes empty.
Since Session("Cart") contains the comma separated values of the product IDs, an empty list would make the following SQL query fail:
select id, name
from products
where id in ()
with the message:
Incorrect syntax near ')'.
You have to show us the portion of code that's reloading the query from Session("Cart"). The query should be reassembled.
But there's one trick you can use! If your product ids are numeric and always greater than zero, change this line:
strCart = String.Empty
to this:
strCart = '-1, '
Update
I will really teach how to fish on this one. :) the problem is here:
Dim strCart As String = String.Empty
If Session("Cart") IsNot Nothing Then
strCart = Session("Cart").ToString
e.Command.CommandText &= " WHERE product.ProductID IN (" + strCart + ") AND culture.CultureID = 'en'"
Else
e.Cancel = True
End If
When cart is empty, Session("Cart") is not Nothing but it's an empty string (provided that you removed the -1 workaround). If Session("Cart") is an empty string the where clause should be " WHERE culture.CultureID = 'en'" only, no mention to product ids. God speed!

Radcombobox inside Radgrid FormTemplate

G'day,
I have a RadComboBox control inside of a RadGrid that is displayed when the InitInsert action occurs. I'm using Entity Framework as a datasource & the results contained within this are correct. My problem is that when I use findcontrol it returns nothing.
If e.CommandName = "InitInsert" Then
RadGrid1.MasterTableView.InsertItemDisplay = Telerik.Web.UI.GridInsertItemDisplay.Bottom
Dim query = From myTable In dbEntity.myTables Select myTable.Name, myTable.ID
Dim mineCompBox = CType(e.Item.FindControl("mineCompBox"), RadComboBox)
mineCompBox.DataSource = mineCompQuery
mineCompRadBox.DataTextField = "Name"
mineCompRadBox.DataValueField = "Id"
mineCompRadBox.DataBind()</code>
I'm having trouble finding any answers that reference FormTemplate without it being an edit form. What am I missing? :-(
Thanks.
I don't have my computer in front of me to test it but I'm pretty sure that either:
1) You are not looking at the right controls collection
2) or the RadComboBox is not create yet or has been created but the ID doesn't match
so you cannot find it
Again not 100% sure. Maybe this can help you its a complete example: http://beecy.net/post/2009/01/07/telerik-radgrid-formtemplate-codebehind.aspx (maybe check you markup against this one)
My problem was solved by using an ItemCreated command. An example can be found here:
http://www.telerik.com/community/forums/aspnet-ajax/grid/find-controls-when-using-editcommand.aspx
The code for my situation was:
Private Sub RadGrid1_ItemCreated(ByVal sender As Object, ByVal e As Telerik.Web.UI.GridItemEventArgs) Handles RadGrid1.ItemCreated
If TypeOf e.Item Is GridEditFormItem AndAlso e.Item.IsInEditMode Then
Dim dbEntity As WebsiteEntities = New WebsiteEntities
Dim myQuery = From myTable In myTables Select myTable.Name, myTable.ID
Dim EditFormItem As GridEditFormItem = DirectCast(e.Item, GridEditFormItem)
Dim myCombobox As RadComboBox = DirectCast(EditFormItem.FindControl("radDropBox"), RadComboBox)
myCombobox.DataSource = myQuery
myCombobox.DataTextField = "Name"
myCombobox.DataValueField = "ID"
myCombobox.DataBind()
End If
End Sub

Resources