Why data binding does not remember the old values? - asp.net

I have a classic ObjectDataSource and a ListView in my page. The List view just displays some data and when switched to edit template it allows the user to change the values. I want the user to edit just some values -- so I bind just these ones in the edit template.
The problem is that the other values suddenly turn to nulls or 0. I tried to bind all of the values at once and it works fine, but I cannot understand why the old/original values just disappear. Is there any way how to bind the old values?
Thanks for help.

The problem is, that only the data that is included into a round-trip to the server will be available in the postback. That includes all that that is bound to BoundFields, TemplateFields or if the Propertyname is included in the DataKey (or DataKeyNames, don't know right now).
The best approach to fix this, and to keep the overhead to a minimum is to add your primary key to the DataKeyNames collection. This allows you to have access to your custom object that contains an unique identifier and all properties that have just changes.
In your Update Method of the ODS (in your custom class) you now need to retrieve the old object by its unique identifier, manually assign the new values and saves your object back to the database

Related

What is the proper way to add records to a V2 odata model with two way binding in SAP UI5?

I have a SAP UI5 V2 odata model with a two way binding to a table and to a form.
The table is displaying all records, and when clicking on a record, I am using setBindingContext to bind the selected table record to the form for editing. When typing in the form, the values dynamically update in the table (because of the two way binding). model.submitChanges() writes the change back to the server.
So displaying the list, and editing records in the list are working just fine.
Now for the problem How to create records with the same form?
I also want to use the same form for adding new records, but I cannot figure out how to unbind the form from a previously selected record, or otherwise create a new blank entry in the data model to be sent to the server.
All of the tutorials I have been able to find on doing UI5 Odata CRUD operations don't really address this problem.
I discovered this example in the documentation which pointed me in the correct direction.
In summary, you use the oModel.createEntry method to create a new entry in the oData Model. You then have to bind this new entry to your form with setBindingContext - this is the part I was missing.

Split Table column in Dynamic data

I am using an integer field in the DB to represent collection of booleans in order to save some space. the integer is used in my Business logic and transformed into collection Boolean attributes.
i'v now decided to add "Admin" section to the site using Dynamic data feature, and i am wondering whether there is an option to show the Booleans that represent that integer.
i know how to Hide a certain column (avoid scaffold) but i don't know how to add "virtual" column to the Dynamic control.
Maybe Sql View is the answer here? is there an easy way to bind the dynamic data into SQL view instead of the real table?
Have you tried creating a custom field template that would handle the logic of splitting/"joining" the boolean values into an integer?
MSDN:
http://msdn.microsoft.com/en-us/library/cc488523.aspx
Video:
http://www.asp.net/learn/3.5-SP1/video-291.aspx

Data Binding fails

I have a form with 30 fields of data on it - mostly TextBox controls displaying string data, but there are 3 dropdownlist comboboxes and one textbox used to display a datetime. I'm using a BindingSource to bind these fields to a custom data object derived from BindingList<>.
Depending on the content of the data in the data source, sometimes a specific field will simply fail to bind - meaning the data from the data source does not get moved to the control. The control that fails is a simple textbox.text / string binding.
I can perform a specific query that in every instance will cause this specific field to fail to bind. I have other queries that can be performed that produce a set of data where the bindings all work perfectly.
My question is - what causes data binding to fail? Will the failure of some other bound field stop all the other bindings from firing?
Here are a few things that you could check
Is there a mismatch in the size of the data field and the field in the UI
Are there any special characters in the data
Is the code that binds the fields not being run in certain circumstances
Is there some code that is clearing the binding
I solved this issue by writing my own binding infrastructure. That gave me more explicit control over when bindings fired and what happened as a result.

Make Gridview interact with something other than properties

We're planning to create a web application where users can build custom "forms," choosing which fields they would like, and how the data in those fields should be represented. Users can then fill out these forms in a DetailsView-like control, thereby creating "documents." The documents can be shown in a DetailsView, or certain fields of several of them can be shown in a GridView. At least, that's the idea.
The problem is that GridView and DetailsView seem to be specifically designed to access Properties on objects that come out of a DataSource. Since we want to have completely arbitrary forms, we can't restrict ourselves to building a class with Properties to represent each field. We have to be able to have any number of dynamically-specified fields on a form.
Is there any way to leverage the existing controls so we don't have to re-implement paging, sorting, and all the other things that GridViews are already set up to do, or will I just have to create my own GridView-like control from scratch?
Edit:
More specifically, the difficulty I am having is in getting inline editing to work on the GridView. For example, let's say that one of the "fields" that is added to a "form" is a calendar field, which should display a date as text in read-only mode, and display a calendar control in edit mode. When the "save" button is clicked, the date selected by the calendar control needs to be saved to the database as the new value for the given field of the given document (i.e. instance of the form). My initial idea was to create a special DataControlField class which, given a form field key, would know how to databind thusly:
FormDocument doc = DataBinder.GetDataItem(cell) as FormDocument;
FormFieldValue fieldValue = doc.FieldValues[FieldKey];
fieldValue.AddReadOnlyControls(cell);
... instead of:
Object dataObject = DataBinder.GetDataItem(cell);
cell.Text = DataBinder.GetPropertyValue(dataItem, FieldKey);
This would probably work for displaying the field values, but if the user tries to edit and save one of the FormDocuments I don't know how I would convince the GridView to do something like this:
doc.FieldValues[FieldKey] = newValue;
Currently, the API for DataControlField uses the ExtractValuesFromCell method to put the property name and value into an IOrderedDictionary. Those values are then applied to the given properties of the objects in the GridView's databound IEnumerable. The problem is, I can't work with properties of an object because in this case the object needs to have a completely arbitrary number of fields.
A GridView can be bound to any object that implements IEnumerable. The advantage of using one of the xDataSource controls is that it can implement paging and sorting for you without any additional code, but you certainly aren't tied to them.
If I understand your question correctly, you do not know the number of columns to display in the GridView until runtime. In that case, I would recommend building an array from your form data and binding the grid to that. You will have to implement paging and sorting yourself.
The DetailsView is not very customizable so you should take a look at the FormView. However, I think you are going to end up dynamically adding controls to whatever container you use.
What you need is totally dynamic GridView. I quess you would have to extend it with the controls ( functionalities ) in your description
Here's what I ended up doing:
I created a new data type that contained a Dictionary of answers, indexed by Field ID.
I created a new type of DataControlField with a FieldId property, which retrieves the proper answer value for that FieldId from the Dictionary mentioned above.
I added data type and data keys properties to this custom DataControlField and overrode the ExtractValuesFromCell method so that it could create a new instance of the answer class and add those values to a Dictionary, which was stored under the property name by which that dictionary would be found in the new data type mentioned in step 1.
I used my own GridView class, used the .NET Reflector to see how the normal GridView calls the ExtractValuesFromCell method, and then changed that so that it would pass the same Dictionary object in to each DataControlField. This way, each field could add to the same Dictionary, rather than replacing the Dictionary that the last one had added under the same property name.
I used a DataFieldGenerator to generate the one of my custom DataControlFields for every field associated with a given form, and I told the GridView to use that DataFieldGenerator to auto-generate its fields.
I set up my ObjectDataSource so that it would know how to save all the answer values from an object of the type mentioned in step 1.
It was tricky, but worthwhile.

Binding gridviews to viewstate until being able to write to database

I recently began working on a project which has many gridviews on a single page. During creation of a new record, the user needs to be able to add/remove/edit these gridviews and then save to the database at the end. The problem with this obviously is that there is no datasource to bind the data too until after its written to the database.
This data represents a 1..* relationship, which is why the gridview data cannot be written to the database until the parent record has been created first.
The best way I have found so far to solve this is to use viewstate. This solution however does not seem ideal to me. I am also forced to manually create the gridview functionality with OnDeleting, OnUpdating, etc so that I can manage the binding of the viewstate with the gridview.
Does anyone have any suggestions on a better way to manage this situation, it seems like it would be a common thing?
UPDATE:
Keep in mind this data needs to be around throughout postbacks.
Use a DataSet as an intermediate connection to your data source. Fill the DataSet with your data and then bind your GridView to the DataSet setting the GridView DataMember to the name of the table it is supposed to bind to.
As the user updates tables it will add/modify records in the DataTables in the DataSet. When the user is done editing and clicks "Save" your code can then update the database from the datasets, either automatically using a DataAdapter, or manually looking at the RowState of the rows in the DataTables.
Use a DataAdapter and a Dataset. Invoke the fillschema method in the adapter to create de metadata (cols, constraints, relations, etc) in the dataset. bind the data tables created to the different grid views. update manually cheking each row rowstate on each table or call the adapter's update method to do it automatically. If you do it automatically you need to define commands for insert, delete, and update in the adapter.

Resources