Identifying object in ItemTemplate and event not firing - c#

I am using a RadListView control with an ItemTemplate that contains a button as shown here:
<ItemTemplate>
<tr class="rlvI">
//more TD elements here
<td>
<telerik:RadButton ID="ENABLEDToggle" runat="server" Width="75" ButtonType="StandardButton" AutoPostBack="true"
ToggleType="CustomToggle" Checked='<%# Enabled_Converter(Eval("ENABLED")) %>' OnCheckedChanged="TaskStateChange_Clicked">
<ToggleStates>
<telerik:RadButtonToggleState Text="Enabled" />
<telerik:RadButtonToggleState Text="Disabled" />
</ToggleStates>
</telerik:RadButton>
</td>
</tr>
</ItemTemplate>
My first question is why is it that when my button is pressed, I do not enter my TaskStateChange_Clicked event handler? It is as if the event is never fired.
Second, whenever a button is clicked, how do I get the object associated with that row?

As for the first question, check how you are binding your RadListView. Problems like this usually appear if controls are bound with data on every postback. So if you have something like
void Page_Load(object sender, EventArgs e)
{
...
RadListView1.DataSource = dataSource;
RadListView1.DataBind();
...
}
replace it with
void Page_Load(object sender, EventArgs e)
{
...
if (!this.IsPostBack)
{
RadListView1.DataSource = dataSource;
RadListView1.DataBind();
}
...
}
Update from comments. Another reason might be that the type of your button is StandardButton while spec implies that event CheckedChanged is fired only when button type is ToggleButton.
As for the second question consider using RadListView's ItemCommand event. This way you can make use of CommandArgument property of RadButton and pass any info you want in it, say object's ID.

Related

Find control in repeater footer returns null for text box

I have two nested repeaters. In the nested one's footer I have text box and file upload controls. I was able to get an instance of the file upload without any problem, but the instance of the text box is null, though both are placed in the footer.
Here is the aspx part representing the footer of the inner repeater:
<FooterTemplate>
<tr class="add_comment">
<td>Add comment </td>
</tr>
<tr>
<td>
<asp:TextBox runat="server" Columns="20" Rows="3" ID="comment_txt" TextMode="MultiLine" Width="60%" CssClass="new_comment" ViewStateMode="Inherit"></asp:TextBox>
</td>
</tr>
<tr class="add_comment">
<td>
<asp:FileUpload ID="uploadImageBtn" runat="server" Text="Add image" OnClick="uploadImage" CssClass="comment_buttons" />
<asp:Button ID="comment_btn" runat="server" OnClick="submitComment" Text="Comment" CssClass="comment_buttons" />
</td>
</tr>
</table>
</FooterTemplate>
This is the C# code where I'm trying to access the controls:
protected void commentsRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if ((e.Item.ItemType == ListItemType.Footer ))
{
Repeater childRepeater = (Repeater)sender;
TextBox commentTextBox = (TextBox)e.Item.FindControl("comment_txt");
String postText = commentTextBox.Text.ToString();
FileUpload upFile = (FileUpload)e.Item.FindControl("uploadImageBtn");
}
}
When running the page I get this error,
Object reference not set to an instance of an object
Which is caused by this line:
String postText = commentTextBox.Text.ToString();
I tried to remove the text box code and retrieve only the upload file and it worked very well. The problem is in accessing the text box.
Edit: The accessed text of the text box and the instance of upload button should be accessed in an onclick event handler of a button in the same page. Thus, I have defined both globally, assigned them the values while executing some nested repeater event of the Repeater like ItemDataBound or the event suggested by Adrian Iftode, which is ItemCreated. Then, in the onclick of the button I used them assuming that they have values since the nested repeater event should be fired before onclick of the button. Upload file instance is retrieved successfully, but the text box is always null.
Global variables declaration:
TextBox commentTextBox;
FileUpload upFile;
Repeater childRepeater;
String postText;
Code inside nested repeater event:
protected void commentsRepeater_ItemCreated(object sender, RepeaterItemEventArgs e)
{
if ((e.Item.ItemType == ListItemType.Footer))
{
childRepeater = (Repeater)sender;
commentTextBox = (TextBox)(e.Item.FindControl("comment_txt"));
postText = commentTextBox.Text.ToString();
upFile = (FileUpload)e.Item.FindControl("uploadImageBtn");
}
}
Code inside onclick:
protected void submitComment(object sender, EventArgs e)
{
Boolean insert = true;
if (upFile.HasFile || !String.IsNullOrEmpty(postText))
{
//some code.
}
The above if statement is only executed if upFile has file, postText is always seen as null.
Can anyone please help me, what is causing this error?
Thank you.
ItemDataBound is not the right event to handle in this situation, because the header and footer templates are not instantiated in for the repeater items.
The proper event is ItemCreated
protected void rp_ItemCreated(Object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Footer)
{
e.Item.FindControl(ctrl);
}
if (e.Item.ItemType == ListItemType.Header)
{
e.Item.FindControl(ctrl);
}
}

How to force enable/disable of controls in aspx?

I have a simple windows form app which I have to migrate to run on a webpage, so I'm trying with aspx(c#).
I have two radio buttons, but at time only one of them should be checked. I implemented the very same code from the original app, but it's not working:
protected void RadioButton1_CheckedChanged(object sender, EventArgs e)
{
if (RadioButton1.Checked == true)
{
RadioButton2.Checked = false;
}
}
protected void RadioButton2_CheckedChanged(object sender, EventArgs e)
{
if (RadioButton2.Checked == true)
{
RadioButton1.Checked = false;
}
}
So why these changes not being applied on the page?
you can use GroupName Property of RadioButton Control.
if you set the same GroupName for set of RadioButtons you don't need to write the Code Behid which you have written in the above Post/Question, as only one radio button can be selected from the group.
but if you want to invoke some action like Disabling TextBox on Particular Radio Button click event you can use following sample code.
Example: in this example i'm taking 3 Radio Buttons all set to Same GroupName, hence only one RadioButton canbe selected at a time.
when user selects/checks a RadioButton1 i'm Disabling the TextBox1.
Note : Please Make sure that your RadioButton AutoPostBack Property set to True otherwise events on RadioButton won't be fired.
Design Code:
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:RadioButton ID="RadioButton1" runat="server" Text="DisableTextBox" GroupName="Group1" AutoPostBack="True" OnCheckedChanged="RadioButton1_CheckedChanged"/>
<asp:RadioButton ID="RadioButton2" runat="server" GroupName="Group1" AutoPostBack="True"/>
<asp:RadioButton ID="RadioButton3" runat="server" GroupName="Group1" AutoPostBack="True" />
Code Behind:
protected void RadioButton1_CheckedChanged(object sender, EventArgs e)
{
if (RadioButton1.Checked)
TextBox3.Enabled = false;
else
TextBox3.Enabled = true;
}
Put the checkboxes in a GroubBox or Panel
You can set the GroupName of both radiobuttons the same, so the Code Behind you wrote is not needed anymore.
Also, check out the RadioButtonList
UPDATE
Your aspx-code should look something like this:
<asp:RadioButton id="RadioButtonEnabled" runat="server" Text="Enabled" GroupName="GroupTxtEnabled" AutoPostBack="True" OnCheckedChanged="RadioButtonEnabled_CheckedChanged"/>
<asp:RadioButton id="RadioButtonDisabled" runat="server" Text="Disabled" GroupName="GroupTxtEnabled" AutoPostBack="True"/>
<asp:TextBox id="TextBox1" runat="server"/>
And in your code-behind:
protected void RadioButtonEnabled_CheckedChanged (object sender, EventArgs e)
{
TextBox1 = RadioButtonEnabled.Checked
}
As you can see, I've used the OnCheckedChanged only at one radiobutton, since both radiobuttons are changed at the same time (property GroupName is equal).

My checkbox on the gridview doesn't trigger an event

I created my gridview with checkboxes inside of it with this code.
<asp:GridView ID="GridView1" runat="server" Width="366px" autogeneratecolumn="false">
<Columns>
<asp:TemplateField>
<HeaderTemplate>
<asp:CheckBox ID="SelectAllCheckBox" runat="server" AutoPostBack="true" oncheckedchanged="SelectAllCheckBox_OnCheckedChanged" />
</HeaderTemplate>
<ItemTemplate>
<asp:CheckBox ID="EachCheckBox" runat="server" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
I tried check/uncheck it.
enter link description here
protected void SelectAllCheckBox_OnCheckedChanged(object sender, EventArgs e)
{
String test = "test";
test = "newtest";
GridView1.DataSource = null;
GridView1.DataBind();
}
But it doesn't trigger any event.
enter link description here
I'm trying to find where my code is missing and searched so far but still can't.
Thank you for your help!
You must use OnItemCreated or OnItemDataBound and link your checkbox with your delegate
void Item_Created(Object sender, DataGridItemEventArgs e)
{
CheckBox cbx = (CheckBox)e.Item.FindControl("SelectAllCheckBox");
cbx.CheckedChanged += SelectAllCheckBox_OnCheckedChanged;
}
The code looks fine and works for me.
I suspect you might be binding the GridView on every postback.
When you click the CheckBox with the event attached it causes the page to refresh. If you bind the CheckBox on Page_Load (or any method that occurs on every trip to the server) it will bind the grid every time you click the CheckBox. In this case it will never get as far as firing your event.
If so, try checking for a postback before binding your GridView.
For example:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
Gridview1.DataSource = myDataSource;
GridView1.DataBind();
}
}

OnServerClick for button not working

I have an html button and I'd like to have a server side click event but it's not firing when the button is clicked and the page does a postback. The button is inside the ItemTemplate for an <asp:ListView id="usersListView"/> that renders a table of information.
aspx
<button runat="server" id="delete" class="btn btn-mini" title="Delete" OnServerClick="delete_Onclick"></button>
aspx.cs
protected void delete_Onclick(object sender, EventArgs e) {
ListViewItem listViewItem = (ListViewItem)((Button)sender).NamingContainer;
if(listViewItem != null) {
Membership.DeleteUser(((Label) listViewItem.FindControl("userName")).Text);
}
}
My guess is that it will not work like this because events raised by nested controls placed in item templates should rather be handled by ListView's ItemCommand event.
For this to work then, you should set button's CommandName and CommandArgument and handle specific values in the listview's ItemCommand.
However, if I remember correcly, the HtmlInputButton does not have CommandName and CommandArgument properties. Instead, use asp:Button
<asp:Button id="delete" runat="server" CommandName="something" CommandArgument="somethingelse" />
and handle the listview's itemcommand:
protected void usersListView_ItemCommand( object sender, ListViewCommandEventArgs e )
{
switch ( e.CommandName ) {
case "something" :
// this is where you handle the button click
}
}
Note that CommandArgument is usually bound to an item-specific value (id perhaps) so that inside the server-side handler you can precisely identify the exact clicked button:
<asp:Button id="delete" runat="server" CommandName="something" CommandArgument="<%# Eval( "id" ) %>" />
protected void usersListView_ItemCommand( object sender, ListViewCommandEventArgs e )
{
switch ( e.CommandName ) {
case "something" :
// this is where you handle the button click
var itemid = e.CommandArgument;
}
}

On ASP.NET ListView with LinqDataSource, display the data when the search button clicked

I have a ListView setup with LinqDataSource and a button that triggers search function. To avoid display data on page_load, I set ListView's DataSourceID in the Click event of the search button, bind it and set result data in LinqDataSource's Selecting event. It works as I expected but It does't look pretty to set DataSourceId in the button Click event every time the search button is clicked. How can I do this in a better and clearer way?
ASPX code:
<asp:LinqDataSource ID="LinqDataSource1" runat="server"
ContextTypeName="WebApplication1.DataClasses1DataContext" EntityTypeName=""
TableName="Persons" onselecting="LinqDataSource1_Selecting">
</asp:LinqDataSource>
<asp:ListView ID="ListView1" runat="server" >...</asp:ListView>
<asp:Button ID="Search" Text="Search" runat="server" Click="Search_Clicked"/>
ASPX.CS code:
protected void Search_Clicked(object sender, EventArgs e)
{
ListView1.DataSourceID = LinqDataSource1.ID;
ListView1.DataBind();
}
protected void LinqDataSource1_Selecting(object sender, LinqDataSourceSelectEventArgs e)
{
//Search Criteria from CheckBoxList and TextBox applied here.
DataClasses1DataContext data = new DataClasses1DataContext();
var query = from result in data.Persons
where result.ID > 2
select result;
e.Result = query;
}
I honestly don't see anything wrong with your approach, however, if you don't like it, an alternate approach would be to just statically set the DataSourceID in your ListView markup as usual, but set Visible="False", and only make it visible once the button has been clicked.

Categories

Resources