Next Available item DDL VB.NET - asp.net

I've got a drop down that works by picking up files in a folder to then display in the dropdown list to the end user.
However if one of the files is deleted or moved, the code breaks if it's mid-way through because the DDL is selecting a file that isn't there.
Forcing postback doesn't seem to solve this issue I tried implementing IF/Else function but could get the code to work for if nothing found then find next that exists.
Any help would be greatly appreciated.
Below is the code I'm using:
Private Sub RefreshDLL()
Dim currentSelected As String = DDL.SelectedValue
DDL.DataSource = IO.Directory.GetFiles(FolderName, "*.txt").Select(Function(f) IO.Path.GetFileName(f)).ToList
DDL.DataBind()
DDL.SelectedValue = currentSelected
End Sub

I am assuming you are referring to my reply here:
Dynamically Add Text Files to DDL in ASP & VB
It is easy to detect whether the file is still available or deleted. But you will also have to put the TextBox inside an UpdatePanel so that it can be updated, when the data inside it is no longer valid. You can put that in the same UpdatePanel if possible, or put it in a separate UpdatePanel with UpdateMode="Conditional". Setting UpdateMode to Conditional will update that TextBox only when you want to update it, thus reducing flickering.
<asp:UpdatePanel runat="server" ID="UpdatePanel2" UpdateMode="Conditional">
<ContentTemplate>
<asp:TextBox ID="TextBox1" runat="server" TextMode="MultiLine" Width="300" Height="250" />
</ContentTemplate>
</asp:UpdatePanel>
And then the code to refresh the DropdownList goes like this:
Private Sub RefreshDropDownList()
Dim currentSelected As String = DropDownList1.SelectedValue
DropDownList1.DataSource = IO.Directory.GetFiles(FolderName, "*.csv").Select(Function(f) IO.Path.GetFileName(f)).ToList
DropDownList1.DataBind()
If IO.File.Exists(IO.Path.Combine(FolderName, currentSelected)) Then
DropDownList1.SelectedValue = currentSelected
Else
OpenSelectedFile()
UpdatePanel2.Update()
End If
End Sub

Related

How to get Repeater's current ItemIndex in code behind

While Container.ItemIndex as a way to get current repeater's item index in data binding expression works perfectly fine <%# Container.ItemIndex %>, it does not work in pure code behind. Container is not declared or inaccessible.
How can I get repeater's current item index here:
<ItemTemplate>
<% If Container.ItemIndex = 2 Then %>
TRUE/some longer HTML here/
<% Else %>
false/some longer HTML here/
<% End If %>
</ItemTemplate>
EDIT
For cases with not much HTML code this will work, but I am looking for Code Render Block solution as per example above.
<%#: If(Container.ItemIndex = 2, "TRUE", "false") %>
Ok, just drop in a button and pick up the repeter row.
So, say we have this repeater markup:
<asp:Repeater ID="Repeater1" runat="server">
<ItemTemplate>
<div style="border-style:solid;color:black;width:290px;float:left;padding:10px">
<div style="padding:5px;text-align:right">
Hotel Name: <asp:TextBox ID="txtHotelName" runat="server" Text ='<%# Eval("HotelName") %>' />
<br />
First Name: <asp:TextBox ID="txtFirst" runat="server" Text ='<%# Eval("FirstName") %>' />
<br />
Last Name: <asp:TextBox ID="txtLast" runat="server" Text ='<%# Eval("LastName") %>' />
<br />
City: <asp:TextBox ID="City" runat="server" Text ='<%# Eval("City") %>' />
<br />
Province: <asp:TextBox ID="Province" runat="server" Text ='<%# Eval("Province") %>'/>
<br />
Active: <asp:CheckBox ID="chkActive" runat="server" Checked = '<%# Eval("Active") %>'/>
<br />
<asp:Button ID="cmdRowC" runat="server" Text="Row Click" OnClick="cmdRowC_Click"/>
</div>
</div>
<div style="clear:both;height:5px"></div>
</ItemTemplate>
</asp:Repeater>
and our code behind to fill this repeater:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If IsPostBack = False Then
LoadGrid()
End If
End Sub
Sub LoadGrid()
Using cmdSQL As New SqlCommand("SELECT * FROM tblHotels ORDER BY HotelName",
New SqlConnection(My.Settings.TEST3))
cmdSQL.Connection.Open()
Repeater1.DataSource = cmdSQL.ExecuteReader
Repeater1.DataBind()
End Using
End Sub
And we now have this:
So now the button code. Note how I just dropped in a standard button.
But, we now can't double click on the button to automatic wire up and create a event.
BUT YOU CAN do this to create a event:
In the button code markup, type in OnClick=
WHEN YOU HIT "=", then intel-sense will pop up a dialog for you to create a button click event like this:
So, now click on create new event. It "seems" like nothing occured, but if we flip to code behind you find the click event stub.
So, now in our click event code we can easy pick up the current repeater row, the values and yes even the index.
The code works like this:
Protected Sub cmdRowC_Click(sender As Object, e As EventArgs)
Dim cBtn As Button = sender
Dim rRow As RepeaterItem = cBtn.Parent
Debug.Print("Row clicked = " & rRow.ItemIndex)
Debug.Print("First Name = " & DirectCast(rRow.FindControl("txtFirst"), TextBox).Text)
Debug.Print("Last Name = " & DirectCast(rRow.FindControl("txtLast"), TextBox).Text)
Debug.Print("Hotel Name = " & DirectCast(rRow.FindControl("txtHotelName"), TextBox).Text)
End Sub
output:
Row clicked = 1
First Name = Darcy
Last Name = Caroll
Hotel Name = Athabasca Hotel
So, just drop in a plane jane button. When you click on it the event stub runs, and as you can see, we pick up the "Repeater row item".
From that row, we can get the row index, and of course pluck out any other control value from that row using find control.
eg:
Dim txtHotel as TextBox = rRow.FindControl("txtHotel")
debug.print ("Hotel name = " & txtHotel.Text)
So, once you have the repeater row, you don't need some container.ItemIndex expression, since the row item lets you get the given index row with:
rRow.ItemIndex
So, ItemIndex is available, and is avilable regardless if you have or include or use the conttin.ItemIndex in the markup.
There is VERY LITTLE need to mess around with that code in the markup.
Note how VERY clean and simple the above is. I suggest you MAKE HUGE efforts to avoid dumping vb code inside of the markup like you are doing. If you even want to convert to c#, or even just maintain that code? Put that code in the code behind area - not in the markup.
As above shows, for repeating data etc., you can use a Repeater, or even often I use a listview - as it allows a repeating layout to be created automatic for you, and without having to write looping code.
******************** EDIT ***************************
Ok, now that we have this working, say we wanted to put in a message in the repeater that
This hotel is Active
or
This hotel is NOT active!
Ok, so in our markup, we could drop in a label like this:
And now from the repeater property sheet, double click here to create the item data bound event:
It is now a simple matter to put in our code logic for each row like this:
Protected Sub Repeater1_ItemDataBound(sender As Object, e As RepeaterItemEventArgs) Handles Repeater1.ItemDataBound
Dim rRow As RepeaterItem = e.Item
Dim ckbox As CheckBox = rRow.FindControl("chkActive")
Dim MyLabel As Label = rRow.FindControl("Label1")
If ckbox.Checked Then
MyLabel.Text = "This Hotel is Active!!!"
Else
MyLabel.Text = "Not active!"
End If
End Sub
And output is now this:
So, once again, to conditional format the repeater, add color to active hotel, or whatever? Use the item bound event.
Say i wanted add to above that the HotelName is to be color blue when active, then we could do this:
Protected Sub Repeater1_ItemDataBound(sender As Object, e As RepeaterItemEventArgs) Handles Repeater1.ItemDataBound
Dim rRow As RepeaterItem = e.Item
Dim ckbox As CheckBox = rRow.FindControl("chkActive")
Dim MyLabel As Label = rRow.FindControl("Label1")
If ckbox.Checked Then
MyLabel.Text = "This Hotel is Active!!!"
Else
MyLabel.Text = "Not active!"
End If
Dim txtHotel As TextBox = rRow.FindControl("txtHotelName")
If ckbox.Checked Then
txtHotel.BackColor = Drawing.Color.AliceBlue
End If
End Sub
Again, nice easy clean code - no mess markup. We seperate the code logic from the markup.
Output now is this:
Again, note how we did not even write ANY looping code here!!!!
So you want to leverage the built in options for the repeater, and for a GridView, listView, and a repeater?
Use the row data bind event - it lets you format, even do math, or whatever you want for EACH row of the repeating controls. And as you can see, its plain jane easy to write code as a bonus.

Change dropdownlist value without autopostback

How to change dropdownlist value based on another dropdownlist value without autopostback in asp.net using vb.net
Well, if you don't post-back, then no code can run.
You could start to use ajax calls. That allows you to call + use server side code without a page post-back. But this means you have to write some JavaScript code client side.
However, a post-back is not the end of the world here.
And there is a in-between choice, in which you ONLY post back the two combo boxes, and that results in quite much ONLY the two combo boxes being posted, and the rest of the page will remain un-touched.
This means asp.net DOES the ajax wire up for you!!!
So, way we have these two combo boxes. First one select city, and 2nd one a hotel in that city.
<div style="float:left">
<h3>Select City</h3>
<asp:DropDownList ID="cboCity" runat="server" Width="168px"
DataValueField="City" DataTextField="City" AutoPostBack="true"></asp:DropDownList>
</div>
<div style="float:left;margin-left:25px">
<h3>Select Hotel</h3>
<asp:DropDownList ID="cboHotels" runat="server" Width="168px"
DataValueField="ID" DataTextField = "HotelName"
></asp:DropDownList>
</div>
Ok, so note that our first combo box has auto post back.
And our code is this:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
' load up City combo
cboCity.DataSource = MyrstP(New SqlCommand("SELECT City from City ORDER BY City"))
cboCity.DataBind()
cboCity.Items.Insert(0, "") ' Add blank row selecting
End If
End Sub
and first combo box code is this:
Protected Sub cboCity_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cboCity.SelectedIndexChanged
' cascade City and limit hotels from given city.
Using cmdSQL As New SqlCommand("SELECT ID, HotelName FROM tblHotels
WHERE City = #City ORDER BY HotelName")
cmdSQL.Parameters.Add("#City", SqlDbType.NVarChar).Value = cboCity.SelectedItem.Text
cboHotels.DataSource = MyrstP(cmdSQL)
cboHotels.DataBind()
cboHotels.Items.Insert(0, New ListItem("Select Hotel", 0))
End Using
And our helper routine to make life easy:
Public Function MyrstP(sqlCmd As SqlCommand) As DataTable
Dim rstData As New DataTable
Using sqlCmd
sqlCmd.Connection = New SqlConnection(My.Settings.TEST4)
sqlCmd.Connection.Open()
rstData.Load(sqlCmd.ExecuteReader)
End Using
Return rstData
End Function
(and NOTE VERY careful, how we NEVER created a connection object and then used it later, but we use the BUILT IN one inside of sql command.
Ok,
now lets change this to NOT full page post back.
Do this:
<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<div style="float:left">
<h3>Select City</h3>
<asp:DropDownList ID="cboCity" runat="server" Width="168px"
DataValueField="City" DataTextField="City" AutoPostBack="true"></asp:DropDownList>
</div>
<div style="float:left;margin-left:25px">
<h3>Select Hotel</h3>
<asp:DropDownList ID="cboHotels" runat="server" Width="168px"
DataValueField="ID" DataTextField = "HotelName"
></asp:DropDownList>
</div>
</ContentTemplate>
</asp:UpdatePanel>
Now give it a try!!! - note how the page does not post-back anymore.
This is still a partial page post back, but ONLY the combo box is sent back to the server, and only part is updated. In fact this is quite much how the new blazer pages with signalR quite much work.
So try the above. You will note that no page post back occurs.

How to clear exisiting dropdownlist items when its content changes?

ddl2 populates based on ddl1 selected value successfully.
My issue is the data that is already present in ddl2 does not clear before appending the new data so ddl2 content just continues to grow every time ddl1 is changed.
<asp:DropDownList ID="ddl1" RunAt="Server" DataSourceID="sql1" DataValueField="ID1" DataTextField="Name2" AppendDataBoundItems="True" AutoPostBack="True">
<asp:ListItem Text="ALL" Selected="True" Value="0"/>
</asp:DropDownList>
<asp:DropDownList ID="ddl2" RunAt="Server" DataSourceID="sql2" DataValueField="ID2" DataTextField="Name2" AppendDataBoundItems="True" AutoPostBack="True">
<asp:ListItem Text="ALL" Selected="True" Value="0"/>
</asp:DropDownList>
<asp:SqlDataSource ID="sql1" RunAt="Server" SelectCommand="sp1" SelectCommandType="StoredProcedure"/>
<asp:SqlDataSource ID="sql2" RunAt="Server" SelectCommand="sp2" SelectCommandType="StoredProcedure">
<SelectParameters>
<asp:ControlParameter Type="Int32" Name="ID1" ControlID="ddl1" PropertyName="SelectedValue"/>
</SelectParameters>
</asp:SqlDataSource>
I have tried re-databinding in code behind on selected index change and also items.clear with little success.
Protected Sub ddl1_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs)
ddl2.Items.Clear()
ddl2.DataSource = sql2
ddl2.DataBind()
End Sub
QUESTION
How to get items present in an asp:dropdownlist to clear before new values are populated when the dropdownlists content is dependent on another dropdownlists selected value?
Please post any code in VB
Using ddl.Items.Clear() will clear the dropdownlist however you must be sure that your dropdownlist is not set to:
AppendDataBoundItems="True"
This option will cause the rebound data to be appended to the existing list which will NOT be cleared prior to binding.
SOLUTION
Add AppendDataBoundItems="False" to your dropdownlist.
Now when data is rebound it will automatically clear all existing data beforehand.
Protected Sub ddl1_SelectedIndexChanged(sender As Object, e As EventArgs)
ddl2.DataSource = sql2
ddl2.DataBind()
End Sub
NOTE: This may not be suitable in all situations as appenddatbound items can cause your dropdown to append its own data on each change of the list.
TOP TIP
Still want a default list item adding to your dropdown but need to rebind data?
Use AppendDataBoundItems="False" to prevent duplication data on postback and then directly after binding your dropdownlist insert a new default list item.
ddl.Items.Insert(0, New ListItem("Select ...", ""))
You should clear out your listbbox prior to binding:
Me.ddl2.Items.Clear()
' now set datasource and bind
Please use the following
ddlCity.Items.Clear();
Just 2 simple steps to solve your issue
First of all check AppendDataBoundItems property and make it assign false
Secondly clear all the items using property .clear()
{
ddl1.Items.Clear();
ddl1.datasource = sql1;
ddl1.DataBind();
}
just compiled your code and the only thing that is missing from it is that you have to Bind your ddl2 to an empty datasource before binding it again like this:
Protected Sub ddl1_SelectedIndexChanged(ByVal sender As Object, ByVal
e As EventArgs)
//ddl2.Items.Clear()
ddl2.DataSource=New List(Of String)()
ddl2.DataSource = sql2
ddl2.DataBind() End Sub
and it worked just fine

checkbox.checked is not working in a listview

I've got an aspx using master pages and .net 4. I've using the same code on 4 different forms. I've copied and pasted it from the other forms that are working. Here is the code.
The listview is named lvMisc_Attachment, here is the Checkbox code
<asp:CheckBox ID="chkChecked" runat="server" Checked='<%#eval("Checked") %>' />
and here is the code behind that is happening when someone clicks a linkbutton, the linkbutton calls teh MiscAttachment_ItemsChecked function.
Private Function MiscAttachment_ItemsChecked() As String
Dim mString As String = String.Empty
For Each lv In Me.lvMisc_Attachment.Items
If CType(lv.FindControl("chkChecked"), CheckBox).Checked = True Then
If mString.Length = 0 Then
mString = CType(lv.FindControl("hfMisc_AttachmentID"), HiddenField).Value
Else
mString = mString & "," & CType(lv.FindControl("hfMisc_AttachmentID"), HiddenField).Value
End If
End If
Next
Return mString
End Function
The checkbox does not show up as being checked when it is. It is getting checked after the page renders.
Add AutoPostback="true" to your checkbox in order to post contol whan he changes
<asp:CheckBox ID="chkChecked" runat="server" Checked='<%#eval("Checked") %>' AutoPostback="true"/>
I found the problem. I forgot to do a if page.ispost=true on the page_Load.. the listview was getting repopulated so the checkbox wasn't checked due to the reload.

Loading a value on the insert command of a detailsview

In a detailsview, how can I prepopulate one of the textboxes on the insertcommand (When the user clicks insert and the view is insert).
I think this would work for codebehind:
Dim txtBox As TextBox = FormView1.FindControl("txtbox")
txtbox.Text = "Whatever I want"
Is this right? What do I need in the aspx (not as sure)? Also, I'm assuming the server-side code will go in the itemcommand or insertcreating event.
I have typed this in VB.NET but I am using C# (I can do both so on a language agnostic forum I might type the problem in another language). I am also using a SqlDataSource, with my parameters and insert/delete/edit commands all created.
I am trying to generate a random GUID (using the GUID object), which will be prepopulated in the textbox.
Also, is the postbackurl property of a button not another way of preserving form state?
Thanks
I would update the field in the DetailsView to a TemplateField:
<asp:TemplateField>
<InsertItemTemplate>
<asp:TextBox ID="txtField" runat="server" Text='<%# Bind("GUID") %>'/>
</InsertItemTemplate>
<ItemTemplate>
<asp:Label ID="lblField" runat="server" Text='<%# Bind("GUID") %>'/>
</ItemTemplate>
</asp:TemplateField>
Then you have two options:
generate your GUID and insert into
your datasource. This may have to be done with SQL since you mentioned using SqlDataSource
remove the binding and access the controls from code in the
DataBound event of your DetailsView
Private Sub dv_DataBound(ByVal sender As Object, ByVal e As EventArgs) Handles dv.DataBound
dim txt as Textbox = dv.FindControl("txtField")
txt.Text = GenerateGUID()
End Sub
I'm guessing you need to use one of detailsview events.
Hook up to ItemCommand, ModeChanging or ModeChanged events and fill your value there.
I am doing something like this as well. I am hiding the DetailsView and showing it when the user clicks a button.
dvDetails.ChangeMode(DetailsViewMode.Insert)
pnlDetailMenu.Visible = True
Dim ColumnTextBox As TextBox
ColumnTextBox = dvDetails.Rows(0).Cells(1).Controls(0)
If Not ColumnTextBox Is Nothing Then
ColumnTextBox.Text = "Initial Value"
End If

Resources