New Posts New Posts RSS Feed: Adding Items to a Child Grid
  FAQ FAQ  Forum Search   Calendar   Register Register  Login Login

Adding Items to a Child Grid

 Post Reply Post Reply
Author
Customer View Drop Down
Senior Member
Senior Member
Avatar
User Submitted Questions to Support

Joined: 30-May-2007
Location: United States
Posts: 260
Post Options Post Options   Quote Customer Quote  Post ReplyReply Direct Link To This Post Topic: Adding Items to a Child Grid
    Posted: 06-Jun-2007 at 3:06pm

Question:

On my master-detail form, I want my user to be able to add detail (child) elements, but I’m having problems implementing this successfully. How can I do this?

 

Back to Top
IdeaBlade View Drop Down
Moderator Group
Moderator Group
Avatar

Joined: 30-May-2007
Location: United States
Posts: 353
Post Options Post Options   Quote IdeaBlade Quote  Post ReplyReply Direct Link To This Post Posted: 06-Jun-2007 at 3:10pm

Answer:

Naturally, the answer depends upon the specific problems you’re having, but there are a few we see over and over again, so let’s just walk through the scenarios.

There are two major variables:

  1. Whether the list feeding the child grid is a ReadOnlyEntityList or a vanilla EntityList; and
  2. What UI mechanism you wish to give the end user to indicate that she wants to add a record.

For discussion we’ll use our familiar standby from our tutorials, a Master-Detail form that displays properties of an Employee in loose controls, and the Employee’s Orders in a grid: 

ReadOnlyEntityList v. EntityList

If you have chained the Employees and Orders BindingSources (as demonstrated in the Fundamentals tutorials), then in effect you are using the list of Orders returned by the current Employee’s Orders property to feed the child grid.  Let’s look at code generated (into the EmployeeDataRow class) for this property by the DevForce Object Mapper:

 

    public virtual ReadOnlyEntityList<Order> Orders {

      get {

        ReadOnlyEntityList<Order> result_;

        if (GetInterceptor<ReadOnlyEntityList<Order>>("Orders", GetOrdersCore, out result_)) return result_;

        return GetOrdersCore();

      }

    }

For the purpose of this discussion, the details of the above code are irrelevant, except for the fact that it returns a ReadOnlyEntityList.  That a list is a ReadOnlyEntityList rather than a vanilla EntityList does not mean that changes cannot be made to the details of a given Order included in such a list: rather, it means that you cannot directly add new Orders to the list, or delete existing Orders from it.  In other words, you cannot execute the second of the following two statements:

 

      Order newOrder = Order.Create(mPersMgr,mCurrentEmployee);

      mCurrentEmployee.Orders.Add(newOrder);

Neither can you execute this statement:

      mCurrentEmployee.Orders.Remove((Order)(mOrdersBS.Current));

So how do you get a new Order into the list, or remove an existing one from it?  Actually, it is very easy, because it also so happens that DevForce automatically configures a ListManager for any list that is returned by a generated relation property. That ListManager watches the PersistenceManager cache for Orders that should be included in the list.  When any such Order appears in the cache (whether by virtue of being newly added to the cache, or modified so that it suddenly belongs to the current Employee), the ListManager makes sure it gets included in the list. When any Order already in the list disappears from the cache, or is modified so that it no longer belongs to the current Employee, it is automatically removed from the list.

So to add a new item to mCurrentEmployee.Orders, you simply add to the PersistenceManager’s cache an Order whose EmployeeId connects it to the current Employee:

      Order newOrder = Order.Create(mPersMgr, mCurrentEmployee);

…or you change the EmployeeId of an existing Order so that it now points to the current Employee:

      someOrder.Employee = mCurrentEmployee;

Similarly, to delete an existing Order, you do the following:

      ((Order)(mOrdersBS.Current)).Delete();

In all cases, the mCurrentEmployee.Orders ReadOnlyEntityList will get updated automatically and instantaneously to reflect the new state of the current Employee’s Orders collection.

Is There Any Down Side to Chaining BindingSources, or Otherwise Using a Parent’s Relation Property to Obtain a List of Child Items?

You are fairly likely to encounter situations where getting your child items from a relation property of the parent will not do what you need. For example, you may need to filter the child items, only showing those that meet an additional condition (above and beyond simply belonging to the particular parent); or you may wish to use a span query when retrieving the children so that you pre-fetch additional parts of their object graphs.  In such situations you must cook your own list. 

You still have the choice of using your own ReadOnlyEntityList with a ListManager that you configure; or of using an EntityList, with or without a ListManager.  The one choice you don’t have is to instantiate your own ReadOnlyEntityList but not provide a ListManager for it.  If you do that, you’ll have no way of altering the contents of the list for an add or delete.

UI Mechanisms for Add & Delete

A second important branch in your implementation decision for adding items to a child grid lies in your choice of UI mechanism.  Basically, there are three choices:

  1. Use a conventional, stand-alone button; or
  2. Use the AddNewItem and DeleteItem buttons on a BindingNavigator; or
  3. Use the grid’s NewItem row for adds, and a combination of selecting the row and pressing the DEL key for deletions.

Naturally, there are other choices, but most are adequately represented by the choice of a stand-alone button.  The important characteristics of that mechanism is that it

    • generates an event that can be handled, and
    • doesn’t attempt to do anything on its own.

As you will see, choices 2 and 3 don’t meet the second criterion:  they do attempt, somewhat unhelpfully, to do things on their own; and their built-in behaviors must be either disarmed, or danced around, to get proper behavior with cached objects.

We’ll take the three approaches in order.

Using Conventional, Stand-Alone Buttons

In this approach you provide a stand-alone Button control to the user to indicate when she wants to add a child record, and another button for deletes.  With this approach you have but two things to worry about:

  1. Making the button do the indicated action, and
  2. Making sure the Enabled state of the button is appropriate for the application context.

By the second part, we mean, for example, that the Delete button should not be enabled when there are no items in the list; and the Add button should be enabled whenever adding a record is a reasonable thing to do. (It may be sufficient just to make sure the Add button is always enabled.)  To disable the Delete button, use the ListChanged event of the BindingSource that supplies the grid with data.  In the handler for that event, check the count on items in the list; if it’s zero, disable the button.

So what about making the button perform the indicated action?  Well, an Add button should call the Create method in the child entity’s class, e.g., Order.Create().  Then, depending upon whether the list into which that new child is to be included is managed, or not, it may be necessary to explicitly add the new Order to the list.  Maybe you also want to call MoveLast() on the BindingSource to which the entities in the list are delivered. That’s about it.

The Delete button should call the Delete() method on whatever child entity is currently selected in the grid. That entity is a DevForce business object, so a side-effect of invoking its Delete() method will be that it is removed from any BindableLists (EntityLists, ReadOnlyEntityLists) in which it is currently included.

Using the AddNewItem and DeleteItem Buttons on a BindingNavigator

This approach is similar to that of using stand-alone buttons, but with the additional wrinkle that the built-in behaviors of the buttons must first be disabled.  What are these built-in behaviors?  Well, the AddNewItem button wants to create a new item by calling a parameterless constructor on the type; but that’s a problem, because DevForce entities, for very good reasons, have no parameterless constructor!  The DeleteItem button, for its part, wants to remove an item from the list that feeds the BindingNavigator’s BindingSource; but when we call Delete() on the selected object, DevForce will see to it that it’s also removed from that list.  We definitely don’t want two different things each removing an item from the list! 

Fortunately, disabling the default behaviors is easy.  Just include the following two statements somewhere in your start-up code for the form or UserControl:

 

      this.mEmployeesBindingNavigator.AddNewItem = null;

      this.mEmployeesBindingNavigator.DeleteItem = null;

By default, the AddNewItem and DeleteItem buttons of said BindingNavigator are assigned to these two properties, respectively.  Once you null them out, those buttons no longer have associated with them any behaviors other than the ones you explicitly code into them.  At that point, programming them becomes exactly the same exercise as in the stand-alone buttons case.

Using the NewItem Row for Adds, and Select / DEL for Deletions

The NewItem row for a grid is that row at the bottom or top of the grid –some vendors let you choose where it lives – the clicking into which causes a new item to be added.  Typically, this row is labelled with an asterisk (*) to indicate its special purpose. You have to set a couple of properties – on the grid, on the list that supplies it, or both – to get this row to show up in the first place; then you have to override or augment what it tries to do for you.  In the case of deleting, you have to handle a grid event.

The details of doing these things are specific to the brand of grid you’re using: .NET, Developer Express, and Infragistics all require slightly different approaches.  These are beyond the scope of this discussion, but are detailed in an article, “Add Delete Child Business Objects in a Grid Using NewItem Row”, included in the “Add-Delete On Child Grid” instructional unit that is shipped with the product (in the 200 Intermediate series of instructional units).

 

Back to Top
 Post Reply Post Reply

Forum Jump Forum Permissions View Drop Down