我们使用数据库中的几个事件日期动态填充我们的下拉列表。
目前,所有低于今天的日期都已停用,我们的用户无法查看。
下一个可用日期大于今天的日期将成为默认的下拉列表值,所有未来日期都可以在下拉列表中显示。
例如,如果我们的日期基准上有以下日期:
2013年2月12日
12/20/203
2014年5月21日
2014年8月8日
2014年10月22日
由于其中三个日期( 2/12 / 2013,12 / 20 / 203,5 / 21/2014 )低于今天的日期,因此这些日期已被禁用,可见。
最接近的可用日期大于今天的日期是8/8/2014,这将成为默认的下拉列表值。
最后,所有未来的日期,例如10/22/2014,也可以在下拉列表中找到。
以下是实现此目的的代码剪辑:
//标记
<asp:DropDownList id="txtEventDate" runat="server">
</asp:DropDownList>
//动态填充下拉列表的代码
Dim cmd As New SqlCommand("Select convert(datetime, dates, 103) dates, CONVERT(VARCHAR(12), dates, 107) as datelist from events", New SqlConnection(ConfigurationManager.ConnectionStrings("Events").ConnectionString))
cmd.Connection.Open()
Dim ddlValues As SqlDataReader
ddlValues = cmd.ExecuteReader()
txtEventDate.DataSource = ddlValues
txtEventDate.DataValueField = "dates"
txtEventDate.DataTextField = "datelist"
txtEventDate.DataBind()
cmd.Connection.Close()
cmd.Connection.Dispose()
//仅显示未来日期和下一个可用未来日期的代码作为默认下拉列表值
For Each items As ListItem In txtEventDate.Items
If (DateTime.Parse(items.Value).CompareTo(DateTime.Today)) < 0 Then
items.Enabled = False
End If
Next
我们的用户希望更改流程,以便他们可以返回更早的日期,并在需要时进行一些更改。
有任何想法如何解决这个问题?
Public Sub PopulateDates()
Dim cmd As New SqlCommand("Select convert(datetime, dates, 103) dates, CONVERT(VARCHAR(12), dates, 107) as datelist from events", New SqlConnection(ConfigurationManager.ConnectionStrings("events").ConnectionString))
cmd.Connection.Open()
Dim lstDates As New List(Of DateTime)()
Using rdr As SqlDataReader = cmd.ExecuteReader()
If rdr.Read() Then
lstDates.Add(DirectCast(rdr("dates"), DateTime))
End If
End Using
lstDates = lstDates.OrderBy(Function(x) x.[Date]).ToList()
Dim nearestDate = lstDates.OrderBy(Function(t) Math.Abs((t - DateTime.Now).Ticks)).First()
txtEventDate.DataSource = lstDates
txtEventDate.DataBind()
txtEventDate.SelectedIndex = txtEventDate.Items.IndexOf(txtEventDate.Items.FindByValue(nearestDate.ToString()))
cmd.Connection.Close()
cmd.Connection.Dispose()
End Sub
答案 0 :(得分:3)
根据您的评论,您似乎想让用户更改旧日期。因此,请删除禁用旧日期的For Each
。
首先,您需要找到与当前日期相同或更接近的最近日期,如下所示
Dim nearestDate = ddlValues.OrderBy(Function(t) Math.Abs((t.dates - DateTime.Now).Ticks)).First()
然后,在执行数据绑定后,使用FindByValue
或FindByText
txtEventDate.SelectedIndex = txtEventDate.Items.IndexOf(txtEventDate.Items.FindByValue(nearestDate.ToString()))
旁注: 总是尝试使用using
语句作为SqlConnection
,SqlCommad
等数据库连接对象,以便资源这些对象使用后会在使用后释放。
更新1:根据您在评论中报告的内容,我对日期格式进行了一些更改(它不是您初始问题的一部分)等等,这里是{的完整代码{1}}。另外,请确保您不必运行之前必须设置最近日期的PopulateDates()
,因为它可能会设置错误的值。如果您得到错误的值,那么最好放置断点并查看哪个对象返回意外数据。
foreach
以下是指向 DEMO 的链接(不幸的是它在C#中)我设置为显示它如何返回正确的数据。
更新2:这是您完整的工作版本(希望它能正常运行)。我在本地尝试从数据库加载数据并通过Public Sub PopulateDates()
Dim cmd As New SqlCommand("Select dates from events", New SqlConnection(ConfigurationManager.ConnectionStrings("events").ConnectionString))
cmd.Connection.Open()
Dim lstDates As New List(Of DateTime)()
Using rdr As SqlDataReader = cmd.ExecuteReader()
If rdr.Read() Then
lstDates.Add(DirectCast(rdr("dates"), DateTime))
End If
End Using
Dim stDates As List(Of [String]) = lstDates.OrderBy(Function(o) o.[Date]).[Select](Function(x) x.[Date].ToString("MMM dd, yyyy")).ToList()
Dim nearestDate = lstDates.OrderBy(Function(t) Math.Abs((t - DateTime.Now).Ticks)).First()
// Dim nearestDate = lstDates.First(Function(x) x >= DateTime.Now.[Date]) // this does the trick too
txtEventDate.DataSource = stDates
txtEventDate.DataBind()
txtEventDate.SelectedIndex = txtEventDate.Items.IndexOf(txtEventDate.Items.FindByValue(nearestDate.ToString("MMM dd, yyyy")))
cmd.Connection.Close()
cmd.Connection.Dispose()
End Sub
检索,一切都按照你想要的方式工作。
您在评论中报告说,从DataReader访问时只返回了一个项目,因为您的原始代码DataReader
将在第一条记录之后退出,但我们需要使用{{ 1}}迭代完整列表。
关于持有不同日期格式的下拉列表的If rdr.Read() Then
字段和while
,我已创建了Value
集合来实现此目的。以下是Text
的完整代码。
Dictionary
HTML标记看起来像你想要的格式。
答案 1 :(得分:0)
完全没有经过测试,但是会像以下那样做你想要的吗?您的项目列表需要进行排序(如果尚未排序),但这应该找到今天或更晚的第一个项目,并将其设置为下拉列表中的所选项目。
更新 - 请尝试SelectedValue
!
For Each items As ListItem In txtEventDate.Items
If (DateTime.Parse(items.Value).CompareTo(DateTime.Today)) >= 0 Then
txtEventDate.SelectedValue = items.Value
Exit For
End If
Next