ASP.NET CheckBox not checked on postback without weird hack - asp.net

I have a GridView with a checkbox column. On clicking a button, all rows with the checkbox checked should be removed. I somehow stumbled upon a strange and hacky solution, and I have no idea why it works. I already searched through related SO questions already.
Related code:
Protected Sub Page_Init(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Init
' I have no idea why this is needed for the checkboxes to work...
Dim x = imageGridView.Rows
End Sub
Protected Sub RemoveButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles removeButton.Click
For Each row As GridViewRow In imageGridView.Rows
Dim selectCheckBox As CheckBox = DirectCast(row.Cells(0).FindControl("selectCheckBox"), CheckBox)
If selectCheckBox.Checked Then
Dim fileName As String = row.Cells(1).Text
ImageList.Remove(ImageList.FindLast(Function(r) r.FileName = fileName))
End If
Next
imageGridView.DataSource = ImageList
imageGridView.DataBind()
End Sub
Aspx:
<asp:GridView ID="imageGridView" runat="server">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:CheckBox ID="selectCheckBox" runat="server" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
The line Dim x = imageGridView.Rows is needed for the rows to be removed. I found this after trying my RemoveButton_Click code in the Page_Init sub, then removing code until it didn't work anymore. Dim x = imageGridView is not enough, and it doesn't work to do the same thing in Page_Load.
My checkboxes are never disabled.
So, simply put, why is it necessary for me to reference imageGridView.Rows in the Page_Init for my code to work?

That is an interesting behavior. I reproduce the problem if I bind the data to the GridView in Page_Load on every postback. In that situation, the check boxes lose their selection state on postback, but not if we refer to imageGridView.Rows in Page_Init, as you observed.
The solution is to bind the data inside an If Not IsPostBack conditional block:
Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
imageGridView.DataSource = ImageList
imageGridView.DataBind()
End If
End Sub
In that case, however, we must NOT refer to imageGridView.Rows in Page_Init. Doing so causes the check boxes to lose their selection state (!?!).
From the source code of the GridView (assuming that this source is reliable), I notice that accessing the Rows collection triggers a call to EnsureChildControls which then calls CreateChildControls. I haven't been able to step into the .NET code to see what happens at that point. Calling these methods in the Page_Init event handler may come earlier than expected in the life cycle of the GridView.
By the way, accessing the HeaderRow and the FooterRow properties also triggers a call to EnsureChildControls, and has the same effect on the selection status of the check boxes.

Related

How to use RadDatePicker inside RadGrid?

Wasn't able to find anything about this situation:
I have two RadDatePicker inside RadGrid for start and end date change
<telerik:RadDatePicker ID="rdpStartDate" Skin="Library" EnableEmbeddedSkins="false" CommandName="StartDateChange" runat="server" />
By itself, they work fine, but now I have a situation when I need to call method when their value has been changed (CommandName was added for this)
I know how to do this outside RadGrid, basically:
Protected Sub rdpStartDateChanged(ByVal sender As Object, ByVal e As Telerik.Web.UI.Calendar.SelectedDateChangedEventArgs) Handles rdpStartDate.SelectedDateChanged
...
...
End Sub
But I wasn't able to do this inside RadGrid, because nothings seems to trigger it.
I tried to catch my command with this (works for buttons at least):
Protected Sub rgLibraryItemCommand(ByVal sender As Object, ByVal e As GridCommandEventArgs) Handles rgLibrary.ItemCommand
But, no, it doesn't see CommandName="StartDateChange"
What I need to do to be able to catch those Date change events if RadDatePicker
is placed inside RadGrid?
You need to identify the control inside the grid which triggers the action. I'm not sure which is the way for Rad to do that but it should be similar this:
Private Sub DataGridView1_ButtonClick(sender As DataGridView, e As DataGridViewCellEventArgs) _
Handles DataGridView1.CellButtonClick
'TODO - Button Clicked - Execute Code Here
End Sub
So you need to find the events for the DataGridViewRow for Rad and substitute them with the ones cell clicking events. This example should get you started.
Subscribing to an event on a control inside a RadGrid does not work the same way, because there could be multiple copies of the control or even none at all, depending on how many records are in the Data Source. Therefore, in order to subscribe to events on these controls, you have to do it manually after the data is bound, either in the ItemCreated event or ItemDataBound event.
Protected Sub rgLibraryItemCreated(ByVal sender as Object, ByVal e As GridItemEventArgs) Handles rgLibrary.ItemCreated
If TypeOf e.Item Is GridDataItem Then
Dim item As GridDataItem = e.Item
Dim rdpStartDate As RadDatePicker = item.FindControl("rdpStartDate")
AddHandler rdpStartDate.SelectedDateChanged, AddressOf rdpStartDateChanged
End If
End Sub

How to give a GridView a SearchResultCollection datasource

I am working on a web application (.net framework 4.0), my application role is to search in the active directory and returns the results in a SearchResultCollection.
My question is how to give my GridView the SearchResultCollection as a datasource?
First check that SearchResultsCollection inherits from IEnumerable:
http://msdn.microsoft.com/en-us/library/system.directoryservices.searchresultcollection(v=vs.110).aspx
It does, now you can use the following methods (taken from http://www.telerik.com/help/aspnet-ajax/grid-data-binding-basics.html):
NeedDataSource event - preferred method
The key to the advanced data binding of a RadGrid control is handling the NeedDataSource event. RadGrid fires the NeedDataSource event each time it needs to be bound to a data source. If, at the time of the event, the DataSource property is not set to a valid data source object, the grid will not behave correctly.
Protected Sub RadGrid1_NeedDataSource(ByVal source As Object, ByVal e As Telerik.Web.UI.GridNeedDataSourceEventArgs) Handles RadGrid1.NeedDataSource
' Ensure that SearchResultsCollection is accessible in your code-behind class or <script runat="server"> code block
RadGrid1.DataSource = SearchResultsCollection
End Sub
On Page_Load
Simple data-binding can be used in simple cases when you do not require the grid to perform complex operations such as: Inserting, deleting, and updating records through custom edit forms (WebUserControl or FormTemplate), Grouping, Hierarchy relations, Filtering, Sorting, Paging
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
RadGrid1.DataSource = SearchResultsCollection
End Sub
Edit:
Manipulate the results to get the information you need:
Private Sub rgItems_ItemDataBound(ByVal sender As Object, ByVal e As Telerik.Web.UI.GridItemEventArgs) Handles rgItems.ItemDataBound
Dim result As SearchResult = TryCast(e.Item.DataItem, SearchResult)
If searchResult IsNot Nothing Then
' Get info you need here, perhaps play with result.GetDirectoryEntry()
' Assign this data to variables, name, department , etc
' Use e.Item.FindControl("ltlDepartment").Text = department
End If
End Sub
Ensure that you define each one of these controls:
<telerik:RadGrid runat="server">
<telerik:GridTemplateColumn HeaderText="Department" UniqueName="Department">
<ItemTemplate>
<asp:Literal id="ltlDepartment" runat="server" />
</ItemTemplate>
</telerik:GridTemplateColumn>
</telerik:radGrid>

Datapager always marks page 1

I'm facing a problem with two Datapagers associated with a Listview. This is my page:
<asp:DataPager ID="PagerTop" runat="server" PagedControlID="pp" QueryStringField="page" PageSize="30"></asp:DataPager>
<asp:ListView ID="pp" runat="server" ItemPlaceholderID="holder" EnableViewState="true" OnPagePropertiesChanging="PagePropertiesChanging">
...
</asp:ListView>
<asp:DataPager ID="PagerBottom" runat="server" PagedControlID="pp" QueryStringField="page" PageSize="30"></asp:DataPager>
and the code behind is as follows
Private Sub Page_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreRender
Dim MyData As List(Of Product)
MyData = ResultsManager.GetResults()
pp.DataSource = MyData
pp.DataBind()
End Sub
Private Sub PagePropertiesChanging(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.PagePropertiesChangingEventArgs)
PagerTop.SetPageProperties(e.StartRowIndex, e.MaximumRows, False)
PagerBottom.SetPageProperties(e.StartRowIndex, e.MaximumRows, False)
pp.DataBind()
End Sub
When I change the page, the listview is updated and shows the results corresponding with the indicated page, and PagerTop shows the selected page. That's how they are supposed to work. But PagerBottom is stucked on page 1 and never changes!
It doesn't matter which pager I click, PagerTop always works and PagerBottom always stays at page 1.
I'm running out of brilliant ideas... what can be wrong here?
a very good example is given here
http://www.c-sharpcorner.com/uploadfile/nipuntomar/datapager-in-Asp-Net-3-5/
just place another data pager with different id without any change. i have tried and worked fine for me.

button add event click event

I have a button within a formview control on my page.
Because the button is contained within the formview, my code-behind can't see it.
So I did this:
Dim btnSave As Button = CType(fvCourse.FindControl("btnSave"), Button)
And then I added an event handler like this:
AddHandler btnSave.Click, AddressOf btnSave_Click
Private Sub btnSave_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
Response.write("hey!")
End Sub
The problem is, I don't think it's working because I never see the "hey!" on my page.
Am I missing something?
Thanks
I don't know about missing something, but I reckon you could do it a simpler way since you're using VB. Give your button a command name and command argument first:
<asp:Button ID="Button1" runat="server" onclick="Button1_Click"
CommandArgument="1" CommandName="yes" />
These can be anything - typically you use the command name to determine which button a user clicked on, and the command argument to show the record id.
In your code-behind, attach a macro to the ItemCommand event of the FormView (which fires when something happens within it):
Protected Sub FormView1_ItemCommand(sender As Object, e As System.Web.UI.WebControls.FormViewCommandEventArgs) Handles FormView1.ItemCommand
Select Case e.CommandName.ToLower
Case "yes"
'test
Label2.Text = "You chose " & e.CommandArgument.ToString
End Select
End Sub Protected Sub FormView1_ItemCommand(sender As Object, e As System.Web.UI.WebControls.FormViewCommandEventArgs) Handles FormView1.ItemCommand
Select Case e.CommandName.ToLower
Case "yes"
'test
Label2.Text = "You chose " & e.CommandArgument.ToString
End Select
End Sub
And in VB, that's all you need to do!
You should use the ItemCreated event of the FormView for such things. If the Button is in the ItemTemplate you need to check for the FormViewMode.ReadOnly, for EditItemTemplate you need to use Edit:
Private Sub fvCourse_ItemCreated(ByVal sender As Object, ByVal e As System.EventArgs) Handles fvCourse.ItemCreated
Select Case fvCourse.CurrentMode
Case FormViewMode.Edit
Dim btnSave As Button = DirectCast(fvCourse.FindControl("btnSave"), Button)
AddHandler btnSave.Click, AddressOf btnSave_Click
End Select
End Sub

ASP.NET, VB: how to access controls inside a FormView from the code behind?

I have a checkbox and a panel inside of a FormView control, and I need to access them from the code behind in order to use the checkbox to determine whether or not the panel is visible. This is the code that I originally used, but since I put the controls inside of the FormView, it no longer works.
Protected Sub checkGenEd_CheckedChanged(ByVal sender As Object, _
ByVal e As System.EventArgs)
If checkGenEd.Checked = True Then
panelOutcome.Visible = True
Else
panelOutcome.Visible = False
End If
End Sub
I've started to figure this out based on other questions I looked up on here, but all of them were in C# instead of VB, so this is as far as I got:
Protected Sub FormView1_DataBound(ByVal sender As Object, ByVal e As System.EventArgs) Handles FormView1.DataBound
If FormView1.CurrentMode = FormViewMode.Edit Then
End If
End Sub
So yeah I'm not sure exactly how to finish it. I'm sorry, this might be pretty basic, but I'm new at this and any help would be appreciated!
EDIT: here's my code now:
Protected Sub FormView1_DataBound(ByVal sender As Object, ByVal e As System.EventArgs) Handles FormView1.DataBound
If FormView1.CurrentMode = FormViewMode.Edit Then
CheckBox checkGenEd = formview1.FindControl("checkGenEd");
Panel panelOutcome = formview1.FindControl("panelOutcome");
End If
End Sub
It's also saying that checkGenEd and panelOutcome are not declared.
EDIT: I changed my code to this but it still doesn't work:
Protected Sub FormView1_DataBound(ByVal sender As Object, ByVal e As System.EventArgs) Handles FormView1.DataBound
If FormView1.CurrentMode = FormViewMode.Edit Then
Dim checkGenEd As CheckBox = FormView1.FindControl("checkGenEd")
Dim panelOutcome As Panel = FormView1.FindControl("panelOutcome")
If checkGenEd.Checked = True Then
panelOutcome.Visible = True
Else
panelOutcome.Visible = False
End If
End If
End Sub
There aren't any errors anymore, but nothing happens when I click the checkbox. I think there needs to be some kind of event to trigger it but I don't know how you can put an event handler inside of an event handler.
With FormView, you have to use find control, as in:
CheckBox checkGenEd = (CheckBox)formview1.FindControl("checkGenEd");
Panel panelOutcome = (Panel)formview1.FindControl("panelOutcome");
You cannot reference a control directly by ID.
HTH.
In VB you need use Directcast
Dim chk As Checkbox = DirectCast(Me.FormView1.FindControl("checkgen"), Checkbox)
FormView has its own event framework. A normal control within a FormView won't generate the postback events you are looking for. I initially made the same mistake. I wanted, like you, to generate some kind of postback that could be intercepted at the server end. Once we get back to the server we can look at the values in checkboxes etc depending on whatever business rules apply. This is what I did.
First of all put all relevant controls within an
<EditItemTemplate>
section within the FormView. (There are other Template tags that may be more appropriate). To generate the postback have a button (for example) like the one below. (This has to be within the EditItemTemplate section as well):
<asp:linkbutton id="UpdateButton"
text="Update"
commandname="Update"
runat="server"/>
You can intercept this at the server with the FormView event ItemCommand. For example:
Private Sub FormView1_ItemCommand(sender As Object, e As System.Web.UI.WebControls.FormViewCommandEventArgs) Handles FormView1.ItemCommand
'your code here
End Sub
Once you are back at the server you can then start looking at the various controls to see what they hold, using findControl if necessary. The button command shown above is an example so you might want to use another control.

Resources