session variable loses value after detailsview new cancel event - asp.net

I have 3 controls on my web page, a dropdownlist, a detailsview, and a listview.
the dropdownlist controls the record to be displayed on the detailsview and the listview.
when the detailsview enters "new" mode I clear the items of the detailsview and clear the values of the dropdownlist:
If e.CommandName = "New" Then
lvRecipeSteps.Items.Clear()
ddRecipeItemNumber.Items.Clear()
End If
this shows the page with no items on the dropdownlist, the detailsview and listview on new/insert mode.
the issue happens when I click the cancel event, then this code is executed
If e.CommandName = "Cancel" Then
ddRecipeItemNumber.DataBind()
ddRecipeItemNumber.SelectedValue = Session("Id").ToString()
End If
the session variable Id gets assign on page load
Sub Page_Load(sender As Object, e As System.EventArgs) Handles Me.Load
Session("Id") = ddRecipeItemNumber.SelectedValue
I get an error: "not set to an instance of an object" pointing to: ddRecipeItemNumber.SelectedValue = Session("Id").ToString()
I want to be able to save the record Id, that is on the dropdown before the new/insert event begins, and then if the event gets cancelled, set the controls back to the record that were displaying before the insert/new action started.
I read that using sessions variables is a good way of doing this, but I most be doing something wrong that when the event cancel is executed, the values is then lost.
Please let me know if I can get some help finding a solution for my problem.
Thank you very much.

place the Session("Id") = ddRecipeItemNumber.SelectedValue inside the condition below:
if (!IsPostBack)
{
Session("Id") = ddRecipeItemNumber.SelectedValue;
}
just need to convert it to VB
UPDATE 1
If your code is not inside a Data control then you could allocate its selected value like the code below:
on your aspx form:
<asp:DropDownList ID="DropDownList2" runat="server"
OnSelectedIndexChanged="DropDownList2_SelectedIndexChanged"
AutoPostBack="true" ></asp:DropDownList>
on your code behind:
protected void DropDownList2_SelectedIndexChanged(object sender, EventArgs e)
{
Session["Id"] = DropDownList2.SelectedItem.Value;
}
UPDATE 2
also if you want to change the selected value on your code this would be the right code to do:
instead of this line ddRecipeItemNumber.SelectedValue = Session("Id").ToString()
use this one
ddRecipeItemNumber.Items.FindByValue(Session("Id").ToString()).Selected = true;

Related

GridView column losing hyperlink when looping through rows

I have an asp.net page written with vb.net that has a gridview table. The table is setup to have a checkbox column for each row. If this checkbox is checked for a row, I do some additional things. One of the other columns also includes a hyperlink on the text for each cell in that column.
I have a button on the page that will loop through and programmatically check each one of the checkboxes. The button does this correctly; however, it also removes the hyperlink from the other column for some reason. Any ideas why?
Here is the code where I set the hyperlinks for the hyperlink column:
Protected Sub gridData_RowDataBound(sender As Object, e As GridViewRowEventArgs) Handles gridData.RowDataBound
'When a row is added to the data grid view we need to add the hyperlink to the zipname column
If e.Row.RowType = DataControlRowType.DataRow Then
Dim cell As TableCell = e.Row.Cells(4)
Dim lnk As HyperLink = New HyperLink
'Set properties of the link
lnk.NavigateUrl = cell.Text
lnk.Text = cell.Text
'Format the filename, filepath, zipname, and username to be lowercase
e.Row.Cells(1).Text = LCase(e.Row.Cells(1).Text)
e.Row.Cells(3).Text = LCase(e.Row.Cells(3).Text)
e.Row.Cells(4).Text = LCase(e.Row.Cells(4).Text)
e.Row.Cells(5).Text = LCase(e.Row.Cells(5).Text)
'Add the hyperlink
cell.Controls.Clear()
cell.Controls.Add(lnk)
End If
End Sub
Here is the code for the check all button:
Protected Sub cmdCheckAll_Click(sender As Object, e As EventArgs) Handles cmdCheckAll.Click
'Check all of the download checkboxes
For Each row As GridViewRow In gridData.Rows
CType(row.FindControl("CheckBox1"), CheckBox).Checked = True
Next
End Sub
As is the usual case with Dynamic Controls, All the dynamically created Hyperlinks in RowDataBound event needs to be recreated every postback.
So, there are 2 options.
1.) Either bind your GridView on every postback :
protected void Page_Load(object sender, EventArgs e)
{
gridData.DataBind();
}
OR
2.) Turn off ViewState for your GridView::
<asp:GridView ID="gridData" EnableViewState="false" ... />.
On using any of above options, the OnRowDataBound event is executed each time postback happens, thus recreating the Dynamic controls. Now you can access the Hyperlinks in your button click event.
Check properly which one of above options is best for your application.

Setting focus to a textbox within an UpdatePanel

I have four textboxes within an UpdatePanel, and AutoPostBack is set to True for all of them. When the user enters a value and hits Enter, I want the cursor to move to the next textbox automatically. When I don't have the controls in an UpdatePanel, the standard textbox.focus method works fine.
I found some code here that led me to create this:
Protected Sub txtField_TextChanged(ByVal sender As Object, ByVal e As EventArgs) Handles txtField1.TextChanged,
txtField2.TextChanged, txtField3.TextChanged
'Based on the textbox where data was changed, move the cursor to the next field.
Try
Dim sm As ScriptManager = ScriptManager.GetCurrent(Me)
'As multiple textboxes fire this same event, determine which textbox triggered this.
Dim MyTextbox As TextBox = TryCast(sender, TextBox)
Select Case MyTextbox.ID.ToString
Case "txtField1"
sm.SetFocus(txtField2)
Case "txtField2"
sm.SetFocus(txtField3)
Case "txtField3"
sm.SetFocus(txtField4)
End Select
Catch ex As Exception
lblError.Text = "Error in [txtField_TextChanged]: " & ex.Message
End Try
End Sub
What is really strange is that this works ONCE on whatever field I try first. After that, the event is fired, but the focus does not change. Is there something additional I need to to for subsequent calls?
I would appreciate any suggestions. Thank you!
Try setting the EnablePartialRendering property of the ScriptManager to false, like so:
<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="false"></asp:ScriptManager>
I hope this helps! Good luck, and happy coding :)

asp.net: Attributes.Add is to save - and how do i read them?

I'm adding in asp.net (vb) an attribute to an image-button:
imgButton.Attributes.Add("myAttr", "true")
This is working fine.
Now i want to read the attribute, but it does not work:
If imgButton.Attributes("myAttr") = "true" Then
..doSomething..
How do I get this thing working?
Edit
I have an asp.net repeater.
In this repeater i have in each itemtemplate two image buttons.
If I'm clicking on an imagebutton, the other imagebutton in this row changes it's URL.
I want that this URL is saved, after clicking on another row's imagebutton.
So I'm adding in the repeater event
ItemCommand
Dim imgButton As ImageButton
If e.CommandName = "imgBtn1" Then
imgButton = CType(e.Item.FindControl("imgBtn1"), ImageButton)
imgButton.ImageUrl = "myURL"
imgButton.Attributes.Add("myAttr1", "true")
ElseIf e.CommandName = "imgBtn2" Then
imgButton = CType(e.Item.FindControl("imgBtn2"), ImageButton)
imgButton.ImageUrl = "myURL"
imgButton.Attributes.Add("myAttr2", "true")
End If
In the Page Load event I'm adding:
If Page.IsPostBack Then
Dim countRepeaterItems As Integer = myRepeater.Items.Count
Dim imgButton As ImageButton
For i As Integer = 0 To countRepeaterItems - 1
imgButton = CType(myRepeater.Items(i).FindControl("imgBtn1"), ImageButton)
If imgButton.Attributes.Item("myAttr1") = "true" Then
imgButton.ImageUrl = "myURL"
End If
imgButton = CType(myRepeater.Items(i).FindControl("imgBtn2"), ImageButton)
If imgButton.Attributes.Item("myAttr2") = "true" Then
imgButton.ImageUrl = "myURL"
End If
Next
End If
While debugging, it still skips everything, because all Attributes are empty (but actually they are not)!
Looks like for VB it should be:
If imgButton.Attributes.Item("myAttr") = "true" Then
EDIT: original answer was for C#:
Should be square brackets on the reads:
If imgButton.Attributes["myAttr"] = "true" Then
http://msdn.microsoft.com/en-us/library/kkeesb2c.aspx#Y0
I guess! May be you have (turn off the viewstate) set EnableViewState=False to the imgButton.
Take a look at this sample:
Markup:
<form id="form1" runat="server">
<asp:Button ID="Button1" runat="server" Text="Button" />
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
</form>
Code:
Protected Sub Button1_Click(sender As Object, e As System.EventArgs) Handles Button1.Click
If Label1.Attributes("myAttr") = "true" Then
Label1.Attributes.Add("myAttr", "false")
Label1.Text = "false is set"
Else
Label1.Attributes.Add("myAttr", "true")
Label1.Text = "true is set"
End If
End Sub
Protected Sub Page_Load(sender As Object, e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
Label1.Attributes.Add("myAttr", "true")
End If
End Sub
EDIT:
May be typo in ItemCommand event code.
imgButton.ImageUrl = "myURL"
imgButton.Attributes.Add("myAttr1", "true") '<----- Correction
Addressing the issue of not finding the attributes set in your page load.
I am not entirely clear on what you are trying to accomplish, but it seems likely that you are running into a problem with the order that events execute. On a post back, the page load event executes, then the event handler for the control causing the post back. If your image button causes the post back, then the attribute is not being set until after the page load event has already completed. However, assuming you are using viewstate, your attribute should be persisted and detected on the following post back.
If this is what is happening to you, then one possible way around it would be to move the code from your page load event to the page pre render event. Pre render occurs after the control's post back events have been handled, and it is one of the last points where you can hook in and make changes to your content before it is committed to viewstate.

Not possible to load DropDownList on FormView from code behind?

I have a UserControl, containing a FormView, containing a DropDownList.
The FormView is bound to a data control.
Like so:
<asp:FormView ID="frmEdit" DataKeyNames="MetricCode" runat="server" DefaultMode="Edit" DataSourceID="llbDataSource" Cellpadding="0" >
<EditItemTemplate>
<asp:DropDownList ID="ParentMetricCode" runat="server" SelectedValue='<%# Bind("ParentMetricCode") %>' />
</EditItemTemplate>
<asp:FormView>
I am trying to populate the DropDownList from the codebehind. If this was not contained in a FormView, I would normally just do it in the Page_Load event. However, that does not work within a FormView, as as soon as I try to do it, accessing the dropdownlist in code, i.e.:
theListcontrol = CType(formView.FindControl(listControlName), ListControl)
...the data binding mechanism of the FormView is invoked, which, of course, tries to bind the DropDownList to the underlying datasource, causing a **'ParentMetricCode' has a SelectedValue which is invalid because it does not exist in the list of items. "Parameter name: value ..." error, since the DropDownList has not yet been populated.
I tried performing the load in the DataBinding() event of the FormView, but then:
theListcontrol = CType(formView.FindControl(listControlName), System.Web.UI.WebControls.ListControl)
...fails, as the FormView.Controls.Count = 0 at that point.
Is this impossible? (I do not want to have to use a secondary ObjectDataSource to bind the dropdownlist to)
Implement the OnDataBinding directly on your DropDownList.
When you bind your formview to some data the OnDataBinding for the DropDownList will fire. At this point you can then load the the values you want into the list and bind the selected value to the loaded list as well.
Here is an example:
<asp:DropDownList ID="ParentMetricCode" runat="server" OnDataBinding="ParentMetricCode_DataBinding" />
Then implement the OnDataBinding:
protected void ParentMetricCode_DataBinding(object sender, System.EventArgs e)
{
DropDownList ddl = (DropDownList)(sender);
// Fill the list items however you want
ddl.Items.Add(new ListItem("1", "1"));
ddl.Items.Add(new ListItem("2", "2"));
// etc...
// Set the selected value
ddl.SelectedValue = Eval("ParentMetricCode").ToString();
}
When DataBind your FormView, everything will start to do its magic :)
Also if you loading the list data for your DropDownList from a DB or something you might want to cache it since each 'row' of data will cause the loading of the list data.
EDIT:
Since you think it's not possible I wrote a quick demo app to prove how it works:
In your aspx file include this:
<asp:FormView ID="fvTest" runat="server">
<ItemTemplate>
<asp:DropDownList ID="ddlTest" runat="server" OnDataBinding="ddlTest_DataBinding"></asp:DropDownList>
</ItemTemplate>
</asp:FormView>
Then in your .cs file:
public class MockData
{
public string ID { get; set; }
public string Text { get; set; }
}
protected void Page_Load(object sender, EventArgs e)
{
List<MockData> lst = new List<MockData>();
lst.Add(new MockData() { ID = "3", Text = "Test3" });
fvTest.DataSource = lst;
fvTest.DataBind();
}
protected void ddlTest_DataBinding(object sender, System.EventArgs e)
{
DropDownList ddl = (DropDownList)(sender);
ddl.Items.Add("1");
ddl.Items.Add("2");
ddl.Items.Add("3");
ddl.Items.Add("4");
ddl.Items.Add("5");
ddl.SelectedValue = Eval("ID").ToString();
}
Run the code... the DropDownList will be loaded with all the values and be set to the correct selected value that was set in the mocked object.
Not sure what else I can do to prove it any better... I think your missing how DataBinding actually works. If you try to do it at the FormView level, the controls don't get made until the FormView is actually bound. When the binding happens, you can trigger each control within the template to do something by implementing it's OnDataBinding event. At that point the current iteration of bound object and it's values are available and that is where you see my code do an Eval("ID").
It is working for me with the OnDataBound event instead of OnDataBinding which occurs before the control is created.
<asp:DropDownList ID="ddlCountry" runat="server" DataSourceID="SqlDataSrcCountries" AutoPostBack="True" DataTextField="name" DataValueField="code" OnDataBound="ddlCountry_DataBound">
</asp:DropDownList>
Code-behind:
Protected Sub ddlCountry_DataBound(ByVal sender As Object, ByVal e As System.EventArgs)
Dim ddlCountry As New DropDownList
Dim strCountry As String = String.Empty
Dim lstItemToFind As New ListItem
ddlCountry = FormViewUsers.FindControl("ddlCountry")
strCountry = Eval("country")
lstItemToFind = ddlCountry.Items.FindByValue(strCountry)
If (Not IsNothing(lstItemToFind)) Then
ddlCountry.SelectedValue = strCountry
End If
End Sub
If you use this on other templates than the Edit you just need to validate:
If (FormViewUsers.CurrentMode = FormViewMode.Edit) Then
End If
Ok, found "a" solution:
1. Call the DDL populate function from the FormView_ItemCreated event.
2. Modify the code to populate the DDL like so:
Public Overloads Shared Sub BindListControl(Of theLLBLgenEntityType As EntityBase) _
(ByVal formView As FormView, _
ByVal listControlName As String, _
ByVal theCollection As CollectionCore(Of theLLBLgenEntityType), _
ByVal DataValueField As EntityField, _
ByVal DataTextField As EntityField, _
ByVal IncludeEmptyItem As Boolean)
If formView.CurrentMode = FormViewMode.Edit Then
Dim theListcontrol As System.Web.UI.WebControls.ListControl
theListcontrol = CType(formView.FindControl(listControlName), System.Web.UI.WebControls.ListControl)
For Each entity As theLLBLgenEntityType In theCollection
theListcontrol.Items.Add(New ListItem(entity.Fields(DataTextField.Name).CurrentValue.ToString, entity.Fields(DataValueField.Name).CurrentValue.ToString))
Next
If IncludeEmptyItem Then
theListcontrol.Items.Insert(0, New ListItem("", ""))
End If
End Sub
It kinda seems to basically boil down to, you cannot do additional "Databinding", programatically at runtime, within a FormView.
(Anyone know why the formatting of my code is all screwed up in this post??)
Update
This solution raises yet another batch of issues, related to inserting new items. After a lot of screwing around I eventually found a way around that. At this point, I am basically at the point where I would recommend either avoiding the FormView control entirely, or definitely avoid programatically altering bound controls. Hopefully, perhaps using seperate data controls for each DropDownList might work better, but this might be wishful thinking as well.

ASP.NET get hidden value from list view on ItemCommand

I have LinkButton and HiddenField in a list view. I want to get the hidden value from HiddenField, so I can store it in Session and when a LinkButton is clicked it transfer the hidden value ( stored in Session) to another page. But I get this error message "Object reference not set to an instance of an object." Here's the function:
Protected Sub lvTimeSheet_ItemCommand(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.ListViewCommandEventArgs) Handles lvTimeSheet.ItemCommand
Dim id As HiddenField = TryCast(e.Item.FindControl("hfTimeSheetId"), HiddenField)
Dim myId As String = id.Value.ToString
Session("myId") = myId
Server.Transfer("Destination.aspx")
End Sub
The mark-up
</asp:LinkButton><asp:HiddenField ID="hfTimeSheetId1" runat="server" Value='<%# Eval("hfTimeSheetId") %>' />
Every time the LinkButton is clicked, it causes error with above error message. Thank you for any input.
My guess would be that the FindControl isn't finding the hfTimeSheetId control within the row. Do you have it designated as a managed control (i.e. runat="server")?
Also, it might help if you provided the ASPX code to see how you're defining the controls.
The FindControl is returning null, hense the exception. Try changing it to:
Dim id As HiddenField = TryCast(e.Item.FindControl("hfTimeSheetId1"), HiddenField)

Resources