I am not setting my Gridview DataSource to a control like SqlDataSource or ObjectDataSource.
Instead I am Binding manually in the code behind using a method I wrote:
protected void Bind()
{
CustomDepartmentGV.DataSource = GetSortedDepartments();
CustomDepartmentGV.DataBind();
}
I am also manually handing update through the Gridview properties:
OnRowUpdating="UpdateRow"
And a simplified version of the UpdateRow method in the code behind:
protected void UpdateRow(object sender, GridViewUpdateEventArgs e)
{
var oldValues = e.OldValues;
}
When I run the code above the oldValues variable is set to a System.Collections.Specialized.OrderedDictionary class but the keys and values collections within that have 0 keys / values.
After researching this quite a bit I found a couple posts that say that e.OldValues is not set unless you set the Gridview DataSource to a control like SqlDataSource or ObjectDataSource. I do not want to use these as I like the flexibility it gives me to write my own methods in code behind before hitting the data access layer objects.
Does anyone know how I can get e.OldValues working or provide an alternative so I can look at the original values of the row being updated in the UpdateRow method?
Note
I am able to get the original values of the Gridview DataKey fields but I obviously don't want to set every column to be a data key.
Suppose the GetSortedDepartments() method returns a Datatable. You can put this datatable in the session (for example) and in the UpdateRow method use the Datakey of the the current row to get the old values from this datatable.
Don't forget to update the datatable and to put it again in the session after a row is updated.
Related
C#, WinForms, DataGridView, DataTable. My form allows the user to enter data into a new row (as opposed to, say, popping up a single record view of the record). When the user clicks my Save button, the click event looks like this:
DataTable dtAddRows = this.SomeFictitiouslyNamedDataSet.SomeFictitiouslyNamedDataTable.GetChanges(DataRowState.Added);
My assumption is that calling GetChanges with that enum is going to get me a set of the rows that were added to the grid at run time. However, it errors out because 1 of the columns "Last_Updated_DT" (which must be displayed and readonly) is a date column that will be populated when we write to the datatable. However, the DataSet has a rule that this column cannot be null.
The problem is, I get an error indicating that the Last_Updated_DT column is actually null (surprise surprise). Its a new row, and the column is readonly in the grid, so of course it is null.
How do I get around this error or stuff a value in that (or those) rows for that column before I actually try to get the added rows?
For the sake of posterity:
private void myGrid_DefaultValuesNeeded(object sender, DataGridViewRowEventArgs e)
{
e.Row.Cells["MyColumnNameGridViewTextBoxColumn1"].Value = String.Empty;
}
Adding that event to my code fixed my issue. I set the value to String.Empty so it wouldnt put a date/time value in the column until after the Save was clicked.
Then, in the Save_Click event, I get the added rows with this code:
DataTable dtAddedRows = this.dsMyDataSet.MyDataTable.GetChanges(DataRowState.Added);
Then, in the TableAdapter.Insert parameter list, I added DateTime.Now for the date parameter.
Eventually call MyTableAdapter.Update method using the DataSet overload.
All fixed.
Hat tip to #KiNeTiC for providing the necessary guidance.
I've found a strange behavior with Telerik RadGrid Datasource using Microsoft LINQ To Sql, which I'd like to know what reason causes it.
Suppose I've a basic grid with OnNeedDataSource event:
<telerik:RadGrid ID="grid" runat="server" OnNeedDataSource="grid_NeedDataSource">
...
</telerik:RadGrid>
Event handler in code-behind:
protected void grid_NeedDataSource(object sender, GridNeedDataSourceEventArgs e)
{
grid.DataSource = Dal.Db.VIEW_DETAILs;
}
On the Microsoft Sql Server, VIEW_DETAIL is defined as a view (which select query joins multiple ordinary tables). One of the source tables (let's say it's name is DETAIL) for the view query uses also a computed column that's present also in the view. Querying the view directly from Sql always returns consistent and updated results.
When in my program the source table DETAIL is updated, I call normally
grid.DataBind()
to update its content. Surprisingly nothing is updated (for instance the computed column mentioned above remains the old value). After dealing with some workarounds, I've found that changing the source above on the grid_NeedDataSource handler to
protected void grid_NeedDataSource(object sender, GridNeedDataSourceEventArgs e)
{
grid.DataSource = Dal.Db.VIEW_DETAILs.Where(x=> 1 == 1);
}
(e.g. adding a Where clause that is always true) the data now is correctly updated.
Any insights on this behavior?
Try calling Rebind() instead of DataBind().
According to Telerik, when you need to reassign the datasource of a RadGrid, you should be calling Rebind(). Check the 2nd section Misusing or Not Using NeedDataSource Event on this Telerik page here for more.
I have a ObjectDataSource which is placed in de source code of my .aspx page, not the code behind, and is used inside an EditTemplate column of a datagrid.
<asp:DropDownList ID="ddlist1" runat="server" DataSourceID="osCreditType" ...
After selecting a value in the dropdown and setting the datagrid state back to ItemTemplate, I have the ValueMember of that DropDownItem in the NewValues collection inside the RowUpdating Event.
protected void GridView1_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
int primary = int.Parse(Convert.ToString(e.NewValues[0]));
}
Now, I want to retrieve some other information from the ObjectDataSource using that primary.
Is the data, used for the dropdown still available in the ObjectDataSource, or will a call to that source from code-behind make the datasource go back to the database
Can I use the ObjectDataSource to retrieve additional information using this primary key, and if so, how do I accomplish it ?
Thanks a lot in advance
You have to remember that the ObjectDataSource is really
just a Binder between your Data Layer and Your Controls.
What would be better is for you in the GridView1_RowUpdating routine
is to use a SqlDataAdapter and go and get the information from the database yourself
and then use that information to change the values of the Updated Row.
You will have a problem trying to run another Query with the Same ObjectDataSource,
cause as soon as you do that the control will try to rebind to the new data.
Hope this helps.
I have an empty GridView object on a page that I bind to a LINQ qry result at run time. The GridView has a 'Select" button that fires the SelectedIndexChanged event and it's inside of this event that I'd like to access the data of one of the fields in the selected row.
So far, I can only find one way to do this, and it seems suboptimal:
protected void GridView2_SelectedIndexChanged(object sender, EventArgs e)
{
GridViewRow row = GridView2.SelectedRow;
string UserID = row.Cells[1].Text;
//Do stuff with the userID
}
So this just access the cell data directly based on the cell index. The UserID just happens to be in the second cell and so it works. But later down the road, the UserID may not be in that same column. It seems like I'd be better off looking up the value of this cell by accessing by the cell's header name, or by any method other than the cell index itself.
Any ideas?
Thanks!
Try this
User user = (User)((DataRowView)row.DataBoundItem).Row;
int userID = user.UserID;
I am assuming you have a class called User and you are binding the DataGridView to may a List
I don't know much about asp.net, but in the C# DataGridView you can index columns directly by column name, i.e.
string UserID = row.Cells["UserID"].Text;
or something like that. Might be worth a try.
You can use following code to retrieve object bound to current SelectedRow.
DataTable dt = (DataTable)<GridViewControl>.SelectedRow.DataItem
(here I have assumed that Grid is bound with DataTable.)
i want to ask a question about how to do paging in ASP.net coding with C#.
the thing i try to do is that, i want to display some content, have multi column and multi rows.
in the actually coding, i have a list of object, let say Object A
class A {
integer id;
string name;
string desc;
}
and want to display this onto the page with pagable functionality.
i do google search, ASP.net offer gridview and listview, but they all require a datasource, which mean that table directly bind to the database.
that is not what i want, coz my list of object A come from some where else, not from my database (e.g it is a composite set of data, which generate in runtime)
so it there anyway i still can use those benifit component, or i have to do it all on my own for the paging???
thx
My advice is to use a GridView, with which you can use an ObjectDataSource, which can take its underlying data from a class method that you specify. So the class method might be (following your code example):
public static List<A> GetAllAs()
{
return myAs;
}
and your aspx page would contain
<asp:ObjectDataSource ID="MyODS" runat="server" TypeName="Namespace.Classname" SelectMethod="GetAllAs" />
<asp:GridView ID="grdMyGridView" runat="server" DataSourceID="MyODS" AllowPaging="True" ... >
The TypeName and SelectMethod attributes of the ObjectDataSource tell it which method, and where, to use to fill the ODS with data. The AllowPaging="True" gives you paging on the GridView automatically.
A DataSource property will also accept a List<> or BindingList<> .
To use this in code:
protected void Page_Load(object sender, EventArgs e)
{
var data = new List<Sample>();
data.Add (...);
GridView1.DataSource = data;
GridView1.DataBind();
}
And maybe some IsPostback logic etc.