Insert extra custom fields from DetailsView - c#

I am using a DetailsView control (C# 4.0) to add a record with an EntityDataSource control. There are some fields that need to be added which I do not want to be visible in the DetailsView control - such as DateAdded and UserId - these fields should be added automatically.
<asp:EntityDataSource ID="edsTasks" runat="server"
ContextTypeName="EKIMV2_MasterModel.EKIMV2_MasterEntities"
EnableFlattening="False" EnableInsert="True"
EntitySetName="tasks" ConnectionString="name=EKIMV2_MasterEntities"
DefaultContainerName="EKIMV2_MasterEntities">
</asp:EntityDataSource>
<asp:DetailsView ID="DetailsView1" runat="server" Height="50px" Width="125px"
DataSourceID="edsTasks" DefaultMode="Insert"
AutoGenerateRows="False" DataKeyNames="task_id"
oniteminserted="DetailsView1_ItemInserted"
oniteminserting="DetailsView1_ItemInserting">
<Fields>
<asp:BoundField DataField="task_name" HeaderText="task_name"
SortExpression="task_name" />
<asp:BoundField DataField="task_desc" HeaderText="task_desc"
SortExpression="task_desc" />
<asp:TemplateField HeaderText="assigned_to" SortExpression="assigned_to">
<InsertItemTemplate>
<asp:DropDownList ID="ddlUsers" runat="server" DataSourceID="edsUsers" DataTextField="UserName" DataValueField="UserId"></asp:DropDownList>
</InsertItemTemplate>
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%# Bind("assigned_to") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:CommandField ButtonType="Button" ShowCancelButton="False"
ShowInsertButton="True" />
</Fields>
</asp:DetailsView>
As you can see above there is no DateAdded field. I want to automatically set this value to today's date. The user doesn't need to add the value or see the field at all. There are other fields that I want to set automatically, but without getting into too much detail I think the DateAdded field gives a good example.
I figure I need to somehow add the extra fields during the ItemInserting event, but I don't know where to start.
protected void DetailsView1_ItemInserting(object sender, DetailsViewInsertEventArgs e)
{
}
I've read elsewhere that maybe I need to keep the extra fields in the DetailsView but hide them? Is that right, it doesn't seem like the right thing to do.
So is it possible to add values to fields that are not actually in the DetailsView?

So the answer lies in hiding the fields in the DetailsView by converting them to TemplateFields then using a HiddenField within the template.
You then need to handle the DetailsView1_ItemInserting() event like so:
protected void DetailsView1_ItemInserting(object sender, DetailsViewInsertEventArgs e)
{
e.Values["date_submitted"] = DateTime.Now.ToShortDateString();
}
The event receives DetailsViewInsertEvenrArgs ("e") which contains a dictionary object called Values. Values contains the data that is passed back to your datasource control (an EntityDataSource) in my case.

Related

Problem with being able to access certain elements in GridView -> TemplateField -> EditItemTemplate

I have this problem with being able to access certain elements in
GridView -> TemplateField -> EditItemTemplate.
To be more clear, I have textbox and button
(in GridView -> TemplateField -> EditItemTemplate) and only one of them must be visible depending on operation. If I want to edit, button must be visible and if I want to add new user then textbox must be visible. I have added my aspx code for you to check and also C# code-behind. The method in C# code is the one which gets called immidiately when I press "Edit" button which lets to edit account details and permissions for one user. And I want that this method would decide whenever to show textbox or button (I have IsUserInsertMode property for that.)
I would be really grateful for someone who would help me out with this.
<asp:GridView CssClass="grid" ID="gridUsers" runat="server"
AutoGenerateColumns="False" DataKeyNames="id"
DataSourceID="dsrcUserList" GridLines="None"
OnRowCommand="gridUsers_RowCommand" OnDataBound="gridUsers_DataBound"
OnRowUpdating="gridUsers_Updating" OnRowUpdated="gridUsers_Updated" EnableModelValidation="True">
<Columns>
<asp:TemplateField HeaderText="Password" ItemStyle-HorizontalAlign="center" ItemStyle-Width="80px">
<ItemTemplate>
*******
</ItemTemplate>
<EditItemTemplate>
**NEED REFERENCES TO THESE TWO ITEMS IN ORDER TO SET THEIR VISIBILITY**
<asp:Button ID="btnEditPassword" Text="Change" runat="server" CausesValidation="false" OnClick="btnEditPassword_Click" Visible="false"/>
<asp:TextBox ID="txtPassword" runat="server" TextMode="Password" Text='<%# Bind("Password") %>' Width="74px" MaxLength="50" Visible="true" />
</EditItemTemplate>
</asp:TemplateField>
**LOTS OF CHECKBOXES LIKE THOSE**
<asp:CheckBoxField DataField="AccessTowsRelease" HeaderText="TowsRelease" ItemStyle-HorizontalAlign="Center">
<ItemStyle HorizontalAlign="Center"></ItemStyle>
</asp:CheckBoxField>
<asp:CheckBoxField DataField="AccessTowsView" HeaderText="TowsView" ItemStyle-HorizontalAlign="Center">
<ItemStyle HorizontalAlign="Center"></ItemStyle>
</asp:CheckBoxField>
<asp:CheckBoxField DataField="AccessSMS" HeaderText="SMS"
ItemStyle-HorizontalAlign="Center">
<ItemStyle HorizontalAlign="Center"></ItemStyle>
</asp:CheckBoxField>
**MY EDIT BUTTON**
<asp:CommandField ButtonType="Link"
ShowEditButton="true" EditText="Edit"
CancelText="Cancel" UpdateText="Save" />
</Columns>
</asp:GridView>
C# code-behind (I have added some of the stuff that I have tried)
// this is called when I press some button which lets me to edit one user data including password
// but when I want to change password, there should be button which would redirect to different
// window to do the password change procedure.
// And when I want to add new user there should be textbox for password, not the button.
protected void gridUsers_RowCommand(Object sender, GridViewCommandEventArgs e)
{
//Found the way to get the index of current row (represents one row of information which is visible for the client in browser)
int rowIndex = Convert.ToInt32(e.CommandArgument);
//if those would be working I wouldn't be here asking for help
btnEditPassword.Visible = true;
txtPassword.Visible = false;
//Can't cast 'System.Web.UI.WebControls.GridView' to type 'System.Web.UI.WebControls.GridViewRow'
Button btnEditPassword = (Button)((GridViewRow)sender).FindControl("btnEditPassword");
//every attempt to use FindControl gets me null
Button btnEditPassword = (Button)this.gridUsers.Rows[rowIndex].FindControl("btnEditPassword");
// my way to check if it works - if its null then I do can't anything (prints to browser console).
if (btnEditPassword != null) Response.Write("<script>console.log('not null')</script>");
else Response.Write("<script>console.log('null')</script>");
}
The RowCommand-event is raised too early for your case. It's raised before the row is going into edit mode, that's why you don't find the controls of your edit-item-template.
First change your markup to handle the RowDataBound-event:
<asp:GridView ... OnRowDataBound="gridUsers_OnRowDataBound" ...>
Then handle this in the OnRowDataBound-event like this:
protected void gridUsers_OnRowDataBound(object sender, GridViewRowEventArgs e) {
// check if row is in edit state
if ((e.Row.RowState == DataControlRowState.Edit) || (e.Row.RowState == (DataControlRowState.Alternate | DataControlRowState.Edit))) {
// look for the control in the row
Button btnEditPassword = (Button)e.Row.FindControl("btnEditPassword");
}
}

Why is textbox.Text returning an empty string?

First let me preface this with the fact that I know this question has been asked a slew of times. I've tried implementing everything I've read and have not resolved my issue yet.
I have a shopping cart being displayed in a GridView and I am trying to get the update function to work. After I click edit (on the row in question) and I change the value in the textbox, and then click update, I am always getting an empty string returned.
I've read countless posts about it being a PostBack issue, however I have encapsulated my DataBind method within an if(!Page.IsPostBack){} so I dont believe that is my issue.
These are the relevant methods in my CodeFile:
protected void Page_Load(object sender, EventArgs e)
{
if (Session["thisCart"] == null)
{
Session["thisCart"] = new ShoppingCart();
}
thisCart = (ShoppingCart)Session["thisCart"];
if (!Page.IsPostBack)
{
FillData();
}
}
private void FillData()
{
gvShoppingCart.DataSource = thisCart.Items;
gvShoppingCart.DataBind();
if (thisCart.Items.Count == 0)
{
lblGrandTotal.Visible = false;
}
else
{
lblGrandTotal.Text = string.Format("Grand Total = {0,19:C}", thisCart.GrandTotal);
lblGrandTotal.Visible = true;
}
}
protected void gvShoppingCart_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
TextBox txtQuantity = (TextBox)gvShoppingCart.Rows[e.RowIndex].Cells[3].Controls[0];
int quantity = Int32.Parse(txtQuantity.Text);
thisCart.Update(e.RowIndex, quantity);
gvShoppingCart.EditIndex = -1;
FillData();
}
And this is the aspx file:
<asp:GridView ID="gvShoppingCart" runat="server" AutoGenerateColumns="False" OnRowCancelingEdit="gvShoppingCart_RowCancelingEdit" OnRowDeleting="gvShoppingCart_RowDeleting" OnRowEditing="gvShoppingCart_RowEditing" OnRowUpdating="gvShoppingCart_RowUpdating" ClientIDMode="AutoID">
<Columns>
<asp:BoundField DataField="NAME" HeaderText="Product name" ReadOnly="True" />
<asp:ImageField DataImageUrlField="IMAGE" DataImageUrlFormatString="~\Images\{0}" HeaderText="Image" ReadOnly="True">
</asp:ImageField>
<asp:BoundField DataField="PRICE" HeaderText="Price" ReadOnly="True" />
<asp:BoundField DataField="QUANTITY" HeaderText="Quantity" />
<asp:TemplateField HeaderText="Total">
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%# Double.Parse(Eval("PRICE").ToString()) * Int32.Parse(Eval("QUANTITY").ToString()) %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField ShowHeader="False">
<EditItemTemplate>
<asp:LinkButton ID="LinkButton1" runat="server" CausesValidation="True" CommandName="Update" Text="Update"></asp:LinkButton>
<asp:LinkButton ID="LinkButton2" runat="server" CausesValidation="False" CommandName="Cancel" Text="Cancel"></asp:LinkButton>
</EditItemTemplate>
<ItemTemplate>
<asp:LinkButton ID="LinkButton1" runat="server" CausesValidation="False" CommandName="Edit" Text="Edit"></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
<asp:CommandField ShowDeleteButton="True" />
</Columns>
</asp:GridView>
I'm usually pretty good at finding answers, but this one has got me stumped.
The site crashes after clicking update because the returned value from int quantity = Int32.Parse(txtQuantity.Text); is "" and obviously you cant parse an int from that.
As for the tag of possible duplicate of "ASP.NET validation error message to change labels text." I was unable to find anything that points me in the direction of an answer.
Call FillData() in Page_PreInit. Otherwise, when the ASP.Net runtime goes to restore ViewState for the grid, including your new Textbox data, there's nowhere to put it yet. Remember that every single server event uses a brand new instance of your page class and must rebuild the entire page from scratch.
This was a royal pain to figure out since I'm just learning ASP.net and C#.
When I was able to make this work on an earlier assignment I wasn't using a Master page, with this project I am. The problem lies in the fact that I am using a <form runat="server"> tag in the Master page. Since you can only have one <form runat="server"> tag per page, my GridView wasn't wrapped in one. Once I removed the Master page and added the <form runat="server"> wrapper around the GridView, everything works as intended.

CommandName = Insert in EditTemplate of ASP.NET ListView throws "Insert can only be called on an insert item"

I am supporting a web application. In that, there are two tables - TaxCode and TaxRate. TaxCode has 1 to many relationship with TaxRate.
The UI has a ListView with LayoutTemplate, ItemTemplate and EditTemplate to show TaxCode. When the users selects a tax code in EditTemplate it shows a CutomGridView that allows the user to create or edit tax rates for that particular tax code. This CustomGridView has 3 rows each has 4 template fields as shown below.
<asp:TemplateField HeaderStyle-CssClass="highlightTitlebar" HeaderStyle-Width="5%" HeaderStyle-Height="30px">
<HeaderTemplate>
<custom:CustomImageButton ID="imgAdd" runat="server" ImageUrl="image/add_round.gif" OnClick="imgAddTaxRateDetail_Click" CausesValidation="False"/>
</HeaderTemplate>
<ItemTemplate>
<custom:CustomImageButton ID="imgEdit" runat="server" ImageUrl="image/edit.gif" CommandName="Edit" />
</ItemTemplate>
<EditItemTemplate>
<asp:ImageButton ID="imgUpdate" runat="server" ImageUrl="image/update.gif" CommandName="Update" />
<asp:HiddenField runat="server" ID="hfId" Value='<%# Bind("Id") %>' />
</EditItemTemplate>
<FooterTemplate>
<asp:ImageButton ID="imgInsert" runat="server" ImageUrl="image/insert.gif" CommandName="Insert" OnClick="imgInsert_Click" />
</FooterTemplate>
Each row in the CustomGridView is a template field. In, below image EffectiveOn section is CustomGridView,
When I try to save TaxRate with proper EffectiveOn and Rate, it throws "Insert can only be called on an insert item. Ensure only the InsertTemplate has a button with CommandName=Insert." error as the ListView doesn't have InsertTemplate. But the record gets inserted into the DB.
Please let me know if there is any way to resolve this issue?
The error is self explanatory.
Take a look at this: https://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.listview.insertitemtemplate(v=vs.110).aspx
So you can do either of these things.
Create an InsertItemplate and insert using the ItemInserted event of the listview
Change the CommandName to CommandName="InsertData" and catch that event on the ItemCommand

Rowdeleteing event in Gridview

I have been trying to write this simple logic of deleting a row from the gridview and from the SQL database of the selected row, but keep getting a null reference to cell, which has the primary key [ID] in a field.
Here's my html:
<asp:GridView ID="grvInventoryEdit" runat="server" BackColor="White" onrowdeleting="grvInventoryEdit_RowDeleting"
onrowediting="grvInventoryEdit_RowEditing"
onrowupdating="grvInventoryEdit_RowUpdating">
<Columns>
<asp:CommandField ShowEditButton="True" />
<asp:CommandField ShowDeleteButton="True" /><asp:TemplateField HeaderText="Id">
<ItemTemplate>
<%#Eval("No")%>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox runat="server" ID="txtEditNo" ReadOnly="True" Text='<%#Eval("No")%>'></asp:TextBox>
</EditItemTemplate>
</asp:TemplateField>........ </Columns> </asp:GridView>
And my back-end code for rowdeleting event is :
protected void grvInventoryEdit_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
TextBox id = (TextBox)grvInventoryEdit.Rows[e.RowIndex].FindControl("txtEditNo");
Asset asset = db.Assets.Single(a => a.No == Convert.ToInt32(id));
db.Assets.DeleteOnSubmit(asset);
db.SubmitChanges();
binddata();
}
and when the event fires, this is what i am seeing while debugging:
I am not sure why i am getting a null value ,though, there is a value for that cell.
Could you tell me what i am doing wrong ?
Regards,
Might be it is due to the readonly property of textbox, not suer.
If you want to use the image button for edit and delete then use
protected void ibtnDelete_Click(object sender, ImageClickEventArgs e)
{
GridViewRow gvRow = (GridViewRow)((ImageButton)sender).NamingContainer;
Int32 UserId = Convert.ToInt32(gvUsers.DataKeys[gvRow.RowIndex].Value);
// delete and hide the row from grid view
if (DeleteUserByID(UserId))
gvRow.Visible = false;
}
For complete code see
You are passing TextBox object instead instead of Text property of TextBox
Asset asset = db.Assets.Single(x=>x.No == Convert.ToInt32(id.Text));
and your TextBox is also coming null means it's unable to find it in GridView, try like this:
TextBox id = e.Row.FindControl("txtEditNo");
Also see this CodeProject article to understand how to use ItemTemplate and EditItemTemplate
why are you adding a second commandfield instead of just enabling the delete button on the existing one.
if you are using a command field you should be supplying an compatible datasource that provides Delete functionality
if you're "rolling your own" delete functionality then just use a regular Button control and supply a CommandName and CommandArgument, such as CommandName="MyDelete" CommandArgument=<row number> where <row number> is supplied via GridView RowDataBound() event.
Regardless of how you choose to implement Delete you should be placing the key field in the GridView DataKeys Property and not as a field within each row. This will make obtaining the PK far easier than what you are trying to do
I guess, in my HTML, i have only the value that's bound to the item, is being displayed, and there are no textboxes in my <ItemTemplate>, hence, it pulls null value. Whereas, in my <EditItemTemplate> there is a textbox, which can pull the value from the cell.
So I changed my HTML to this:
<asp:TemplateField HeaderText="Id">
<ItemTemplate>`<asp:label runat="server" ID="lblEditNo" ReadOnly="True" Text='<%#Eval("No")%>'></asp:label>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox runat="server" ID="txtEditNo" ReadOnly="True" Text='<%#Eval("No")%>'></asp:TextBox>
</EditItemTemplate>
</asp:TemplateField>
and no change in my codebehind, and this resolved the issue.

Troubles retrieving data from within OnRowCommand from a GridViews

If I have this <asp:ButtonField runat="server" DataTextField="Name" CommandName="GetName"></asp:ButonField> Within a GridView. Is there any way to retrieve the DataTextField (Name) from the OnRowCommand method?
<asp:GridView ID="GridView1" runat="server"
AllowPaging="True" AutoGenerateColumns="False"
DataSourceID="ObjectDataSource_Names"
DataKeyNames="ID,ModuleId" OnRowCommand="ChangeName">
Or alternatively, is there any way to make CommandName into an attribute where the command is dynamically entered based on given data, similar to the difference between DataTextField vs TextField.
I added <asp:BoundField DataField="Name" /> Then you can retrieve it using the same method here: GridView.onRowCommand Method
All I need to do now is find out a way to hide the field. If anyone knows how to, please let me know. Visible="false" gets rid of the field all together...
Not really sure if this is the best way, but it works:
Make your column a templatefield and bind the name value to a asp:hiddenfield control:
<asp:TemplateField>
<ItemTemplate>
<asp:HiddenField ID="hfName" runat="server" Value='<%# Eval("Name") %>'>
</asp:HiddenField>
</ItemTemplate>
</asp:TemplateField>

Categories

Resources