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.
Related
I need help choosing between Telerik RadGrid and DevExpress ASPxGridView for Asp.Net based on unique filtering requirements. The data lives in denormalized Vax files. All data access is via Sql Server stored procedures calling ODBC Connx queries to the flat files. Stored procedure parameters are used to filter the data. Without any filter thousand of records are returned.
I've successfully displayed all records on two test ASP.net pages, one with DevExpress ASPxGridVIew and the other with Telerik's RadGrid. In code I databind each grid to the stored procedure that returns over 26,000 rows. The sproc is called via an Entity Framework function import that fills an IEnumerable<Customer> which becomes the datasource of each respective grid. I'm able to use the filter features of both grids and they seem to work nicely.
My problem is that before the grid filter is applied all of the thousands of rows are returned from the stored procedure. I'd like to intercept the grid's filter parameters and apply them to my stored procedure parameters. That way far fewer records will be accessed.
Can this be done with either 3rd party grid and if so how?
Thanks in advance.
It seems it can be achieved using a RadFilter to the RadGrid. One example here.
But in general, looks like you'd need to add a handler to ItemCommand, and perform the appropriate filter based on the CommandName, for example. You could then just rebind the data.
The Rad Filter will also allow you to use it without being directly tied to another control or datasource. The filter has an option to extract a filter expression in many different forms (linq provider is one of them). You can then apply that expression to your datasource. We are doing something similar. We have a page where we dynamically create the rad filter with the types of fields and filter options. The user then uses the rad filter UI to create the filter based on the desired fields, then we extract a filter expression we can apply to a datatable that is created on the page that shows the data.
Here is the code for extracting the filter expression from the filter:
var provider = new RadFilterSqlQueryProvider();
provider.ProcessGroup(myRadFilter.RootGroup);
var sqlFilterExpression = provider.Result;
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
I'm using a detailsview control to update a record, however in this particular case there's only one field that can be changed out of a many. The update method for my object takes all fields as parameters. When the detailsview's updating method fires, the values for the readonly fields (those rendered as a Label) are not available in the e.NewValues collection.
I'm currently grabbing a reference to the object when the detailsview is databound (in the objectdatasource selected event handler), storing it in session and manually adding entries to the e.NewValues collection when updating fires. It works but seems kind of heavy handed.
So, is there a better way to get the read only values back into my update method? Or is there a better way of doing this altogether?
There should be an OriginalValues collection too, which may have the collection of readonly values... can you verifiy that?
HTH.
Here's the setup
I have a DetailsView whose DataSource is an ObjectDataSource.
The ObjectDataSource has two methods, select and update, that are stored procedures defined in a TableAdapter.
The Select stored procedure takes 1 parameter--the record id--and returns the fields populated in the DetailsView.
The Update stored procedure takes three parameters--the record id, and two data fields.
The select process works fine.
However, when the I submit the update, I get the following error:
ObjectDataSource could not find a non-generic method Update that has parameters: [all 21 table columns]
I am trying to only pass the (3) necessary fields to the Update stored procedure, but the DetailsView is apparently trying to update using all of the fields it received from Select.
I know that I can access the NewValues collection from DetailsViewUpdateEventArgs, but I don't see a way to remove any of the parameters so that they match the definition in the stored procedure, the TableAdapter, and the ObjectDataSource.
Any ideas?
Perhaps this tutorial can provide some insight. As long as you specify your update method and update parameters in your datasource, this should work fine.
I've been able to work around the problem for now by simply removing the unneeded values from the NewValues collection in the DetailsViewUpdateEventArgs. However, this is not optimal, since I've added another point of failure if there are changes to the stored procedure or the form.
I'd still like to know if a TemplateField can be set to ReadOnly the way that a BoundField can (see comments below Aaron's answer).
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.