I have declaratively created a LinqDataSource and DataList and bound them in markup. I have created an ItemTemplate and Edit Template.
I have bound the DataLists oneditcommand and oncancelcommand to methods in the code behind.
<asp:DataList ID="MyDataList" runat="server" DataSourceID="LinqDataSource1" RepeatDirection="Horizontal"
Font-Bold="False" Font-Italic="False" Font-Overline="False" Font-Strikeout="False"
Font-Underline="False" HorizontalAlign="Center" RepeatColumns="4"
oneditcommand="MyDataList_EditCommand"
oncancelcommand="MyDataList_CancelCommand"
>
<ItemTemplate>
<div style="margin: 5px;">
<asp:LinkButton Text="Edit" CommandName="Edit" style="float:right" runat="server" />
// Other markup
</div>
</ItemTemplate>
When I click the LinkButton in the ItemTemplate, it runs the following code:
protected void DataList_EditCommand(object source, DataListCommandEventArgs e)
{
MyDataList.EditItemIndex = e.Item.ItemIndex;
MyDataList.DataBind();
}
This works fine and puts the selected item in the DataList into edit mode.
The Edit Template:
<EditItemTemplate>
<div style="margin: 5px;">
<asp:LinkButton Text="Cancel" style="float:right"
runat="server" CommandName="cancel" CausesValidation="false"/>
//other markup
</div>
</EditItemTemplate>
When I click the cancel button in the edit template, It does not fire the method in the code behind (the breakpoint doesn't get hit).
The Code that should be run when cancelling never get's run, so I can not exit the edit mode back into normal read mode:
protected void MyDataList_CancelCommand(object source, DataListCommandEventArgs e)
{
PhotoDataList.EditItemIndex = -1;
PhotoDataList.DataBind();
}
Can anyone think of a reason for this?
---- UPDATE
It seems that it is just the second firing of an event on the DataList that doesn't work, as I have know bound to the ItemCommand event, and was going to intercept the DataListCommandEventArgs.CommandName property and do something based on that. If you click the Edit link button, the ItemCommand method fires (with no code body at all), but the second time you click the edit link button, the ItemCommand method does not get hit.
The name of your DataList is : "MyDataList"
but Cancel event calls PhotoDataList!
protected void MyDataList_CancelCommand(object source, DataListCommandEventArgs e)
{
PhotoDataList.EditItemIndex = -1;
PhotoDataList.DataBind();
}
I can't duplicate your problem, I ran this demo code and all events and templates worked fine:
How to: Allow Users to Edit Items in DataList Web Server Controls
Do you have any errors in your event logs? Also, I don't see the DataKeyField defined, how are you selecting your data?
Related
I'm using an asp.net 4 web site project (C#) in VS2008 and I have a FormView with ItemUpdated event:
<asp:FormView ID="FormView1" runat="server" DataSourceID="ds1" OnItemUpdated="FormView1_ItemUpdated">
<EditItemTemplate>
<asp:TextBox ID="TextBox1" runat="server" Text='<%# Bind("col1") %>' />
</EditItemTemplate>
</asp:FormView>
protected void FormView1_ItemUpdated(object sender, EventArgs e)
{
FormView1.DataBind(); // adding this line even doesn't help
TextBox box = FormView1.FindControl("TextBox1") as TextBox;
box.Enabled = false;
}
But I can't figure out, why an extra "FormView1.DataBind()" or Render(?) happens AFTER the ItemUpdated event. The result is that my code in the ItemUpdated event gets like "overwritten" and the TextBox1 doesn't get disabled.
When I set a breakpoint to the last line "box.Enabled = false;" then I see that after the ItemUpdated event it jumps to the aspx page again and steps through the TextBoxes.
Disabling this TextBox1 from another GridView1_SelectedIndexChanged works fine.
Is there any way to see the "current lifecycle progress" in debugging?
EDIT:
To clarify the reasoning...
I have a GridView1 where selecting the item populates the abovementioned FormView1. The point is that I need to disable some of the TextBoxes in the FormView1 based on, for example, user access levels.
Selecting the item from GridView1 disables the TextBox1 just fine, but when I click the Update button on the FormView1 then all TextBoxes are enabled, even if I see in the debugger code running through the GridView1_SelectedIndexChanged() function. And after I re-select the gridview item, the correct TextBoxes are disabled again.
Using even this code:
<asp:FormView ID="FormView1" runat="server" DataSourceID="ds1" DefaultMode="Edit" OnItemUpdated="FormView1_ItemUpdated">
<EditItemTemplate>
<asp:TextBox ID="TextBox1" runat="server" Text='<%# Bind("col1") %>' />
<asp:TextBox ID="TextBox2" runat="server" Text='<%# Bind("col2") %>' />
<asp:Button ID="Btn1" runat="server" CommandName="Update" Text="Update" />
</EditItemTemplate>
</asp:FormView>
protected void GridView1_SelectedIndexChanged(object sender, EventArgs e)
{
if (UserAccess() == false) {
TextBox box2 = FormView1.FindControl("TextBox2") as TextBox;
box2.Enabled = false;
}
}
protected void FormView1_ItemUpdated(object sender, EventArgs e)
{
GridView1_SelectedIndexChanged(sender, e);
}
Maybe I should disable my Textboxes via another event?
This doesn't make sense, please explain more about why you are trying to disable the TextBox, have you just left the ItemTemplate off in your question? or is it actually missing? if it's missing why?
The TextBox is in the FormView's EditItemTemplate, so will only be visible when the FormView is in edit mode. After clicking update or cancel the TextBox will no longer be rendered, and the ItemTemplate is rendered instead. So there should be no need to set the TextBox to be disabled.
EDIT
Ok since you edited your question. You need to use the OnDataBound event of the FormView, which occurs at the end of binding, and disable your TextBoxes at that point.
aspx
<asp:FormView ID="FormView1" runat="server" DataSourceID="ds1"
OnDataBound="FormView1_DataBound">
<EditItemTemplate>
<asp:TextBox ID="TextBox1" runat="server" Text='<%# Bind("col1") %>' />
</EditItemTemplate>
</asp:FormView>
aspx.cs
protected void FormView1_DataBound(object sender, EventARgs e)
{
if (UserAccess() == false) {
TextBox box2 = FormView1.FindControl("TextBox2") as TextBox;
box2.Enabled = false;
}
}
Rather then using gridview selected Index change you can use DataBound event on formview, so your logic would fire everytime the formview is rebind.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Calling a functon in code behind by using an imagebutton in a gridview
I have an ImageButton within a gridview in .aspx on clicking this imagebutton i have to call a function.
This is how i tried and the function was not being called.
Code inside.aspx page:
<GridView ......>
<asp:HyperLink ID="HyperLink2" runat="server" NavigateUrl='<%# DataBinder.Eval(Container.DataItem,"VehID","mngVeh.aspx?delid={0}") %>'>
<asp:ImageButton runat="server" ID="DeleteUrlImageButton" ImageUrl="~/images/delete.jpeg" width='24' height='24'
OnClick="DeleteUrlImageButton_Click"
OnClientClick="return confirm('Are you sure you want to delete?');" />
</asp:HyperLink>
</GridView>
code in .aspx.cs page:
public void DeleteUrlImageButton_Click(object sender, EventArgs e)
{
//code to perform the necessary action.
}
I think you're mixing controls up here.
I would use an ImageUrl on the asp:hyperlink itself, and also the OnClick property. You can handle the OnClientClick by using javascript inside the NavigateUrl property.
I don't see a reason for having a nested ImageButton - I doubt this even works.
Or, just remove the asp:hyperlink completely and do a redirect inside the OnClick event.
The problem here is twofold: First, the click event does not bubble up through the GridView, which is why the event is not firing. Second, that there will be an ImageButton for each row of the GridView, and you need to identify which row the event originated from (or more accurately, which underlying datasource record that row corresponds to).
A common way to approach this problem is to use the ImageButton.CommandName and ImageButton.CommandArgument properties, and handle the GridView.RowCommand event.
Markup:
<asp:GridView ID="GridView1" runat="server" OnRowCommand="GridView1_RowCommand">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:ImageButton runat="server" ID="DeleteUrlImageButton" ImageUrl="~/images/delete.jpeg"
Width='24' Height='24' OnClientClick="return confirm('Are you sure you want to delete?');"
CommandName="MyDelete" CommandArgument='<%# Eval("RecordId") %>' />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Code:
protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
if ((e.CommandName == "MyDelete") && (e.CommandArgument != null))
{
//Add delete code here using e.CommandArgument to identify the correct record.
// For instance:
MyDataObject obj = new MyDataObject();
obj.RecordId = int.Parse(e.CommandArgument.ToString());
MyDataObject.Delete(obj);
}
}
Edit: I see you provided the name of the ID field in your example, so you would probably want to replace "RecordId" in my example with "VehID".
I'm brand new at this, using vs2010 with asp.net and c#, and I'm trying to use a button click event to display forms on my "Add Product" page (the forms will be textbox/label based for inputting data), using items from a dropdownlist of products. Which methods are available/is there a 'best practice' for this sort of thing? I've been fooling around with an if (Dropdownlist.SelectedIndexChanged) statement, but I'm not quite clear on why the syntax requires the SelectedIndexChanged method to preclude a += or -=. Thoughts?
The SelectedIndexChanged method has the += because you are adding an event handler to a specific elements event. Is the button you click on the Add Product page? If so for the OnClick event you could just set your form details based on the DropDownList SelectedItem or SelectedIndex. You may also need to wrap that panel in an UpdatePanel so that it can update visibility without reloading the whole page.
<asp:UpdatePanel ID="updateFormPanel" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:Label ID="lblName" runat="server" Text="" />
<asp:TextBox ID="txtDetails" runat="server" Text="" />
//More TextBox's or whatever you want
</ContentTemplate>
</asp:UpdatePanel?
<asp:DropDownList ID="ddlProductCategory" runat="server" />
<asp:Button ID="btnAddProduct" runat="server" OnClick="AddProduct_Click" Text="Add Product" />
//Code File Behind
protected void AddProduct_Click(Object sender, EventArgs e)
{
lblName.Text = ddlProductCategory.SelectedItem.Text;
txtDetails.Text = ddlProductCategory.SelectedItem.Value;
}
I've been working for a long time with GridViews and DetailsViews, but yesterday I've come across a new scenario, which I quite do not understand.
I have a GridView with ImageButton (CommandName="Insert") which will change the mode of the DetailsView to Insert. Afterwards I'll look for a DropDownList inside that DetailsView and add some items dynamically. Works fine, but one first the first time I press that ImageButton. If I click on "Cancel" in the DetailsView and press the ImageButton again, the .FindControl() Method returns null. What life cycle problem am I facing here?
I've created this sample: (To make it run in your Visual Studio, just bind a DataSource to the DetailsView, otherwise it will not be rendered)
Markup:
<asp:GridView ID="gvCategory" runat="server" OnRowCommand="gvCategory_RowCommand">
<Columns>
</Columns>
<EmptyDataTemplate>
<asp:ImageButton ImageUrl="~/images/add.png" ID="ibAdd" runat="server" CommandName="Insert" />
</EmptyDataTemplate>
</asp:GridView>
<asp:DetailsView ID="dvCategory" runat="server" Width="150px" AutoGenerateRows="false"
AutoGenerateInsertButton="True" DataSourceID="LinqDataSource1">
<Fields>
<asp:TemplateField HeaderText="foo">
<InsertItemTemplate>
<asp:DropDownList ID="ddlCategory" runat="server" Width="150"></asp:DropDownList>
</InsertItemTemplate>
</asp:TemplateField>
</Fields>
</asp:DetailsView><asp:LinqDataSource ID="LinqDataSource1" runat="server"
ContextTypeName="WebApplication1.DataClasses1DataContext"
TableName="Categories"></asp:LinqDataSource>
Codebehind:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
this.gvCategory.DataBind();
}
}
protected void gvCategory_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "Insert")
{
this.dvCategory.ChangeMode(DetailsViewMode.Insert);
DropDownList _ddlCat = (DropDownList)this.dvCategory.FindControl("ddlCategory");
if (_ddlCat != null)
{
_ddlCat.Items.Clear();
_ddlCat.Items.Add(new ListItem() { Text = "-- empty --", Value = "-1" });
}
}
}
I have also tried using a ItemTemplate, and not a InsertItemTemplate, but this results in the same. After using the ChangeMode-Method the DetailsView.CurrentMode == InsertMode. The only thing I can think of is, that the markup is already generated for the ItemTemplate and changing the Mode to InsertMode can't affect the rendered markup, or something like this.
Does anybody have a solution to this? =)
I think you are on the right track. It's hard to tell without seeing all of the code, but basically any time you change the rendering mode of a row in a repeater-type control you need to rebind it so that it's re-rendered. The fact that FindControl is returning NULL means only one thing: THE CONTROL IS NOT THERE. Which means it was not rendered. You can verify this by looking at the control hierarchy.
So, in your handler for Cancel are you rebinding?
I need to access a label control in a listview when I've clicked a button (that is on the same row)...
Does anyone know how to do this please? :(
See below for more of an insight...
ASPX Page:
<asp:ListView ID="ListView1" runat="server" DataSourceID="DataSource">
<LayoutTemplate>//Etc </LayoutTemplate>
<ItemTemplate>
<asp:Label ID="lblDone" runat="server" Visible="false">Your vote has been counted</asp:Label>
<asp:Button ID="voteButton" runat="server" Text="Vote" CommandArgument='<%#Eval("id") %>' OnClick="voteOnThis" />
</ItemTemplate>
Code Behind:
protected void voteOnThis(object sender, EventArgs e)
{
Button myButton = (Button)sender;
Voting.vote(int.Parse(myButton.CommandArgument));
// Here i would like to access the 'label' lblDone and make this Visible
}
In this simple case, I should consider using Javascript (JQuery)
<asp:ListView ID="ListView1" runat="server" DataSourceID="DataSource">
<LayoutTemplate>//Etc </LayoutTemplate>
<ItemTemplate>
<asp:Label ID="lblDone" runat="server" style="visibility:hidden">Your vote has been counted</asp:Label>
<asp:Button OnClientClick="showLblDone()" ID="voteButton" runat="server" Text="Vote" CommandArgument='<%#Eval("id") %>' OnClick="voteOnThis" />
</ItemTemplate>
now, define inside a script tag the showLblDone function:
<script>
function showLblDone (){
$(this).siblings('span').show();}
</script>
You can also call this function with a parameter if you want to show/hide on every click, or you can use .toggle() instead of .show().
In this case you must add a div (or a Panel) inside the ItemTemplate.
You need to hook into the listview row bind and add the information you want to have when clicked. Using this, you can add an attribute to the button that you read back on click, for example...
If you posted some actual code, I could probably help some more.