views:

230

answers:

1

The functionality I am trying to use is: - Create a ObjectDataSource for selection and updating controls on a web page (User Control). - Use the DataObjectTypeName to have an object created that would send the data to an UpdateMethod. - Before the values are populated in the DataObjectTypeName’s object, I would like to pre-populate the object so the unused items in the class are not defaulted to zeros and empty strings without me knowing whether the zero or default string was set by the user or by the application.

I cannot find a way to pre-populate the values (this was an issue back in 2006 with framework 2.0). One might ask “Why would anyone need to pre-populate the object?”. The simple answer is: I want to be able to randomly place controls on different User Controls and not have to be concerned with which UpdateMethod needs to handle which fields of an object.

For Example, let’s say I have a class (that reflects a SQL Table) that includes the fields: FirstName, LastName, Address, City, State, Zip. I may want to give the user the option to change the FirstName and LastName and not even see the Address, City, State, Zip (or vice-versa). I do not want to create two UpdateMethods where one handled FirstName and LastName and the other method handles the other fields. I am working with a Class of some 40+ columns from multiple tables and I may want some fields on one screen and not another and decide later to change those fields from one screen to another (which breaks my UpdateMethods without me knowing).

I hope I explained my issue well enough.
Thanks

A: 

This is hardly a solution to the problem, but it's my best stab at it.

I have a GridView with its DataSourceID set to an ObjectDataSource.

Whenever a row is updated, I want the property values in the object to be selectively updated - that is - only updated if they appear as columns in the GridView.

I've created the following extension:

public static class GridViewExtensions
{
    public static void EnableLimitUpdateToGridViewColumns(this GridView gridView)
    {
        _gridView = gridView;
        if (_gridView.DataSourceObject != null)
        {
            ((ObjectDataSource)_gridView.DataSourceObject)
                .Updating += new ObjectDataSourceMethodEventHandler(objectDataSource_Updating);
        }
    }

    private static GridView _gridView;

    private static void objectDataSource_Updating(object sender, ObjectDataSourceMethodEventArgs e)
    {
        var newObject = ((object)e.InputParameters[0]);
        var oldObjects = ((ObjectDataSource)_gridView.DataSourceObject).Select().Cast<object>();

        Type type = oldObjects.First().GetType();

        object oldObject = null;

        foreach (var obj in oldObjects)
        {
            if (type.GetProperty(_gridView.DataKeyNames.First()).GetValue(obj, null).ToString() ==
                type.GetProperty(_gridView.DataKeyNames.First()).GetValue(newObject, null).ToString())
            {
                oldObject = obj;
                break;
            }
        }

        if (oldObject == null) return;

        var dynamicColumns = _gridView.Columns.OfType<DynamicField>();

        foreach (var property in type.GetProperties())
        {
            if (dynamicColumns.Where(c => c.DataField == property.Name).Count() == 0)
            {
                property.SetValue(newObject, property.GetValue(oldObject, null), null);
            }
        }
    }
}

And in the Page_Init event of my page, I apply it to the GridView, like so:

protected void Page_Init()
{
    GridView1.EnableLimitUpdateToGridViewColumns();
}

This is working well for me at the moment.

You could probably apply similar logic to other controls, e.g. ListView or DetailsView.

I'm currently scratching my head to think of a way this can be done in a rendering-agnostic manner - i.e. without having to know about the rendering control being used.

I hope this ends up as a normal feature of the GridView or ObjectDataSource control rather than having to hack it.

jonathanconway