Problem with DetailsView and ObjectContainerDataSource

Topics: Web Client Software Factory, User Forum
Mar 26, 2007 at 7:15 PM
I've got a view that shows a single BusinessEntity (returned from a Service) that is set using the presenter pattern as the data source of an ObjectContainerDataSource control. I have two bound columns on the DetailsView, one is read only, both are strings. When I click the "Edit" button of the details view and then change the non-read-only field and "Update" it, the controller code that updates the entity correctly only updates the non-read-only field. However when the DetailsView re-renders after the postback, the read only field now appears blank.

Anyone used read-only bound fields on a DetailsView and found a way to work around this?

Thanks,
-Jayme
Developer
Mar 27, 2007 at 5:48 PM
Edited Mar 27, 2007 at 5:56 PM
Hi Jayme, the DetailsView control (as all the DataBoundControls) do not pass read only fields to data source controls. That is why you would experience the same behavior if you used the ASP.NET ObjectDataSource control.

The ObjectContainerDatasource has some events (Inserting, Updating, Deleting), that are raised before an action is performed. These events let you change the collections of values that are used to create and populate the business object being inserted/updated/deleted. In your case, you can use the Updating event to add the read only value to the collection of new values that the ObjectContainerDataSource will to use to build up the new instance. To do this, follow these steps:


1. Make sure you have a TemplateField defined for the read only field, as shown below. You need this so you can access the control that holds the read only value from your code behind.

<asp:TemplateField HeaderText="ReadOnlyText" SortExpression="ReadOnlyText">
     <EditItemTemplate>
           <asp:TextBox ID="ReadOnlyTextBox" ReadOnly=”true” runat="server" Text='<%# Eval("ReadOnlyField") %>'></asp:TextBox>
     </EditItemTemplate>
     <ItemTemplate>
           <asp:Label ID="Label1" runat="server" Text='<%# Bind("ReadOnlyField") %>'></asp:Label>
     </ItemTemplate>
</asp:TemplateField>
2. Handle the Updating event and add the read-only value to the NewValues collection:

protected void ObjectContainerDataSource1_Updating(object sender, Microsoft.Practices.Web.UI.WebControls.ObjectContainerDataSourceUpdatingEventArgs e) 
{
      TextBox tx = DetailsView1.FindControl("ReadOnlyTextBox") as TextBox;
      if (tx != null)
      {
          e.NewValues["ReadOnlyText"] = tx.Text;
      }
}
That should solve the problem.

Let me know if this is helpful for you

Ezequiel Jadib
http://staff.southworks.net/blogs/ejadib
Mar 30, 2007 at 1:57 PM
Edited Mar 30, 2007 at 2:00 PM
Thanks Ezequiel.

This seems like it should be simplified however. Would it be best to report a request to make this work better here, or in the ASP.NET team's forums?

-Jayme
Mar 30, 2007 at 2:00 PM
Edited Mar 30, 2007 at 2:00 PM
Actually I just realized this may not solve the problem. When using the DetailsView I'm doing something like this:

<asp:DetailsView ID="XDetails" DataSourceID="XDataSource" DataKeyNames="Id" runat="server">
  <Fields>
    <asp:BoundField DataField="Name" SortExpression="Name" ReadOnly="True" />
    <asp:BoundField DataField="Url" SortExpression="Url" ControlStyle-Width="400" />         
    <asp:CommandField ShowCancelButton="True" ShowEditButton="True" ButtonType="Button" />
  </Fields>
</asp:DetailsView>
<websf:ObjectContainerDataSource ID="XDataSource" DataObjectTypeName="X.Entities.ServiceConnection" runat="server" OnUpdated="XDataSource_OnUpdated" />

Is there a way to grab the row-specific instance of the bound column in this case so that after an edit, the corresponding label displays the old value?

-Jayme
Jun 22, 2007 at 3:19 PM
Edited Jun 22, 2007 at 3:20 PM
Hi All,

I am trying to use the ObjectContainerDataSource and Gridview and the Edit Event to permit my user to edit some columns of the gridview.
Well, when the user click in update button, inside de gridview to finalize the edition is called the method below:

protected override int ExecuteUpdate(IDictionary keys, IDictionary values, IDictionary oldValues)
{
*Guard.CollectionNotNullNorEmpty(keys, String.Format(CultureInfo.CurrentCulture, Properties.Resources.NoKeysSpecified), "keys");
Guard.ArgumentNotNull(values, "values");*

ObjectContainerDataSourceUpdatingEventArgs updatingEventArgs =
new ObjectContainerDataSourceUpdatingEventArgs(DictionaryHelper.GetReadOnlyDictionary(keys), values, oldValues);
OnUpdating(updatingEventArgs);
if (updatingEventArgs.Cancel)
return 0;

object newInstance = CreateInstance();
TypeDescriptionHelper.BuildInstance(keys, newInstance);
TypeDescriptionHelper.BuildInstance(values, newInstance);
int rowsAffected;
object oldInstance = FindInstance(keys);
if (oldInstance != null)
{
int index = Data.IndexOf(oldInstance);
Dataindex = newInstance;
rowsAffected = 1;
}
else
{
rowsAffected = 0;
}
OnDataSourceViewChanged(EventArgs.Empty);

ObjectContainerDataSourceStatusEventArgs updatedEventArgs = new ObjectContainerDataSourceStatusEventArgs(newInstance, rowsAffected);
OnUpdated(updatedEventArgs);

return rowsAffected;
}

That method calls another one below:

public static void CollectionNotNullNorEmpty(ICollection collection, string message, string argumentName)
{
if (collection == null)
throw new ArgumentNullException(argumentName);

* if (collection.Count == 0)
throw new ArgumentException(message, argumentName); *
}

In this last method I receive an exception cause there are no items in the collection. I really don´t know how to resolve that. Tried almost everything I know, but with no success.

Please, its a simple thing I need to do, that is to update an only one column in gridview and after that, I finish the process clicking a button to update those datas into database.

Thanks for any support.
Aug 20, 2007 at 11:19 AM
Hi
am also using objectcontainerdatasource control in details view every thing is fine ...
but when am trying to update am getting "objectId " is readonly actually DataKeyNames="objectId " here this id is read only i cant make changes to this property
which is comming from other module

is ther any way to update values in database with this datakeynames="objectid" is readonly

plz help me

thanx
Nov 17, 2007 at 7:10 PM
In regard to MOliveira's post above I have also seen this issue. It can be resolved by setting the DataKeyNames property in the DetailsView or FormView - well, that's the solution I've found in the past!