Cancel AddNew Csla 4.1

Cancel AddNew Csla 4.1

Old forum URL: forums.lhotka.net/forums/t/10788.aspx


RumbleCow posted on Wednesday, October 19, 2011

Read through previous posts on this topic and cannot find a working solution.  If 'AddingNew' event is entered in the binding source there does not seem to be a way to cancel.  The most popular post is for 3.7.1.0 and not seeing posting since.  I need a solution for 4.1.  Objects derived from 'DynamicBindingListBase' are working fine but not derived from 'BusinessBindingListBase' exhibit this problem.  Please help...I've been working on this for days.

StefanCop replied on Thursday, October 20, 2011

What do you mean by 'DynamicEditableRootCollection', subclass of DynamicBindingListBase?

As far as I know, only BindingList raise an AddingNew event, other use CollectionChanged.  I don't belive you can "cancel" or deleting/removing from within the event handler (this would change the collection, which is already in a change).

The caller who invoked AddNew() might do a list.Remove(newChild).

RumbleCow replied on Monday, October 24, 2011

Yes, when deriving a class from The BusinessBindingListBase I am looking to solve the problem when attempting to cancel the AddNew within the BindingSource's  "AddingNew" event as follows

 

        private void BindingSourceInvoiceLineEditList_AddingNew(object sender, System.ComponentModel.AddingNewEventArgs e)

        {

            try

            {

 

                // Required user to select product before adding new row

                using (FormSelectProduct f = new FormSelectProduct(showQuantity: true))

                {

                    if (f.ShowDialog() == DialogResult.OK)

                    {

                        InvoiceLineEditListItem newLine = InvoiceLineEditListItem.NewInvoiceLineEditListItem();

 

                        newLine.ProductID = f.ProductInfo.ProductID;

                        newLine.ProductCode = f.ProductInfo.ProductCode;

                        newLine.ProductName = f.ProductInfo.ProductName;

                        newLine.BrandName = f.ProductInfo.BrandName;

                        newLine.Price = f.ProductInfo.Price;

                        newLine.Quantity = f.Quantity;

 

                        e.NewObject = newLine;

 

                        // refreshes object binding

                        this.BindingSourceInvoiceLineEditList.ResetBindings(false);

                    }

                    else

                    {

                        // WORKINGHERE [HANDLE CANCELING OF PRODUCT SELECTION]Sad

                    }

                }

            }

            catch (Exception exc)

            {

                MessageBox.Show(exc.Message);

            }

        }

 

StefanCop replied on Monday, October 24, 2011

AddingNewEventArgs Class states:
If the collection also implements the ICancelAddNew interface, the item will be provisionally added, waiting a subsequent commit or rollback.

DynamicBindingListBase<T> finally inherits System.ComponentModel.BindingList<T>, which implements ICancelAddNew.

So, I guess you can use "CancelNew(int itemIndex)".


RumbleCow replied on Monday, October 24, 2011

I've tried this.  AddingNew event errors upon exit with the following:

 

StefanCop replied on Monday, October 24, 2011

From where is this exception been thrown? From AddNew (--> before your event handler), or within your event handler (InvoiceLineEditListItem.NewInvoiceLineEditListItem();) ?

What platform do you use: Winforms, WP, SL?

RumbleCow replied on Monday, October 24, 2011

I need to backup here.  The exception is happening when deriving from the 'BusinessBindingListBase' and NOT the 'DynamicBindingListBase'. The 'DynamicBindingListBase' is working fine when binding to a DataGridView.   SORRY!!

The exception is thrown when leaving the 'AddingNew' event of the BindingSource when the e.NewObject is not set.

Using Csla 4.1 and Winforms.

StefanCop replied on Monday, October 24, 2011

Have you tried something like this? 

else
 {
      // WORKINGHERE [HANDLE CANCELING OF PRODUCT SELECTION]
      
int index = ((IBindingList) sender).IndexOf(e.NewObject);
      (ICancelAddNew)sender).CancelNew(index);
}

RumbleCow replied on Monday, October 24, 2011

Thisstatement compiles:

int index = ((System.ComponentModel.IBindingList)sender).IndexOf(e.NewObject);

This statement does not:

(System.ComponentModel.ICancelAddNew)sender.CancelNew(index);

Would you expect the value of index to be -1?

StefanCop replied on Monday, October 24, 2011

No.

Sorry, I'm mislead. I thought the new object has already been added and you need to cancel the addition. But now I've no more ideas.

tmg4340 replied on Monday, October 24, 2011

Based on what I can find (and remember from my WinForms days), you're pretty much out of luck.  The way BindingSource is set up to work, it's going to add an item when "AddNew" is called.  If you don't do anything in the AddingNew event, it just tries to call the default constructor of the object type, and you can't stop that.  So you're going to have to work around it.

I don't know how your UI is set up, so I don't know how you're getting to the "AddNew" call.  But it sounds like you're going to have to make the default constructor public for your child item and set a flag if the add should be cancelled.  Then, outside of your event, you'd check that flag and cancel the add via calling CancelEdit if necessary.  Not the cleanest solution, but it's what I see is available given the options.  And again, without knowing how your UI is set up, I don't know how easy it will be to implement that.

HTH

- Scott

RumbleCow replied on Monday, October 24, 2011

Thanks all for the help, guess I'll have to go the route of capturing the info up front in a separate form and only after the user has indicated 'add'' and all is validated will the AddNew get called.  I do not want to expose the default constructor.

Is this fixed in WPF?  We are likely to go WPF before this becomes an issue.

tmg4340 replied on Monday, October 24, 2011

XAML-based binding is a whole different beast, with a whole different set of interfaces/collections available.  The base CSLA classes you use are different depending on what UI technology you're supporting (XAML-vs-non-XAML), so a switch could very well require that you revisit your BO code (beyond the relatively simple search-and-replace required for the base classes).  Plus, when you move to the XAML world you are going to want to take a hard look at MVVM, which changes the whole way you approach building UI's.  You don't have to go that route, but if you don't you may end up fighting a few things.

In terms of your direct question, I believe this is "fixed", but in the WPF world it depends on which grid you go with.  There is no Microsoft-supplied grid "out of the box" for WPF, and the DataGrid from the WPF Toolkit... has issues (and, as best as I can tell, isn't actively being worked anymore).

Finally, for what it's worth, creating public constructors (default or otherwise) for your CSLA BO's is pretty much becoming the norm.  Certain environments require them, and in those that don't having public constructors can make design-time experiences much better.

HTH

- Scott

Copyright (c) Marimer LLC