static void RegisterColumnControllers()
        {
            GridManager.RegisterColumn(Person.StateColumn, MaxWidth(50));
            GridManager.RegisterColumn(Person.ZipColumn, MaxWidth(40));
            GridManager.RegisterColumn(Person.PhoneColumn, MaxWidth(95));
            GridManager.RegisterColumn(Payment.MethodColumn, MaxWidth(70));

            GridManager.RegisterColumns(new[] { Payment.AccountColumn, Pledge.AccountColumn }, MaxWidth(100));

            GridManager.RegisterColumn(EmailAddress.ActiveColumn, new ColumnController(c => {
                c.MaxWidth = 50;
                c.ShowEditorOnMouseDown = true;
                c.ToolTip = "Shul emails will only be sent to checked email addresses.";
            }));

            GridManager.RegisterColumns(
                new[] { Pledge.ModifiedColumn, Payment.ModifiedColumn },
                new ColumnController(c => {
                c.DisplayFormat.FormatType   = FormatType.DateTime;
                c.DisplayFormat.FormatString = "g";
            })
                );

            GridManager.RegisterColumns(new[] { Payment.CommentsColumn, Pledge.CommentsColumn }, new CommentsColumnController());

            GridManager.RegisterColumn(Person.LastNameColumn, new ColumnController(c => {
                c.SortOrder = ColumnSortOrder.Ascending;
                c.SummaryItem.DisplayFormat = "{0} People";
                c.SummaryItem.SummaryType   = SummaryItemType.Count;
            }));
            GridManager.RegisterColumn(MelaveMalkaInvitation.AdAmountColumn, new ColumnController(c => {
                c.DisplayFormat.FormatType   = FormatType.Numeric;
                c.DisplayFormat.FormatString = "c";
                c.OptionsColumn.ReadOnly     = true;
                c.OptionsColumn.AllowEdit    = false;
            }));

            GridManager.RegisterColumn(
                Pledge.AmountColumn,
                new ColumnController(c => {
                c.DisplayFormat.Assign(c.DefaultEditor.DisplayFormat);                          //Copy currency format

                c.MaxWidth = 85;
                c.SummaryItem.DisplayFormat = "{0:c} Total Pledged";
                c.SummaryItem.SummaryType   = SummaryItemType.Sum;
            })
                );
            GridManager.RegisterColumn(
                Payment.AmountColumn,
                new ColumnController(c => {
                c.DisplayFormat.Assign(c.DefaultEditor.DisplayFormat);                          //Copy currency format

                c.MaxWidth = 85;
                c.SummaryItem.DisplayFormat = "{0:c} Total Paid";
                c.SummaryItem.SummaryType   = SummaryItemType.Sum;
            })
                );

            GridManager.RegisterColumn(
                c => c.DataType == typeof(DateTime) && c.Name == "DateAdded",
                new ColumnController(c => {
                c.OptionsColumn.ReadOnly  = true;
                c.OptionsColumn.AllowEdit = false;
            }));
            GridManager.RegisterColumn(
                c => {
                var fkc = c as ForeignKeyColumn;
                return(fkc != null && fkc.ForeignSchema == Person.Schema);
            },
                new PersonColumnController()
                );
            GridManager.RegisterColumn(Payment.DepositColumn, new DepositColumnController());
            GridManager.RegisterColumn(Pledge.SubTypeColumn, new SubTypeColumnController());

            GridManager.RegisterColumn(MelaveMalkaSeat.MensSeatsColumn,
                                       new ColumnController(c => c.Caption = MelaveMalkaSeat.MensSeatsCaption));
            GridManager.RegisterColumn(MelaveMalkaSeat.WomensSeatsColumn,
                                       new ColumnController(c => c.Caption = MelaveMalkaSeat.WomensSeatsCaption));
        }
        //TODO: Group summaries
        #region Behaviors
        static void RegisterBehaviors()
        {
            //TODO: Delete LoggedStatements?
            GridManager.RegisterBehavior(JournalAd.Schema,
                                         DeletionBehavior.WithMessages <JournalAd>(
                                             singular: a => "CAUTION! Only delete an ad if its shape is gone.\r\nTo delete a healthy ad, double-click it, then click the Delete Ad button in the ribbon.\r\nEither way, any pledges, payments, or seating reservations will NOT be deleted.\r\n\r\nAre you sure you want to delete the row for ad #" + a.ExternalId + "?",
                                             plural: set => "CAUTION! Only delete an ad if its shape is gone.\r\nTo delete a healthy ad, double-click it, then click the Delete Ad button in the ribbon.\r\nEither way, any pledges, payments, or seating reservations will NOT be deleted.\r\n\r\nAre you sure you want to delete the rows for ads #" + set.Join(", ", j => j.ExternalId.ToString()) + "?"
                                             )
                                         );

            GridManager.RegisterBehavior(RelativeLink.Schema,
                                         DeletionBehavior.WithMessages(
                                             "relative link",
                                             "relative links"
                                             )
                                         );
            GridManager.RegisterBehavior(Person.Schema,
                                         DeletionBehavior.Disallow("You cannot delete rows from the master directory.\r\nIf you really want to delete someone, call Schabse.")
                                         );
            GridManager.RegisterBehavior(RaffleTicket.Schema,
                                         DeletionBehavior.WithMessages <RaffleTicket>(
                                             singular: t => "Are you sure you want to delete ticket #" + t.TicketId + "?",
                                             plural: set => "Are you sure you want to delete " + set.Count() + " tickets?"
                                             )
                                         );
            GridManager.RegisterBehavior(Caller.Schema,
                                         DeletionBehavior.WithMessages(
                                             "Melave Malka caller",
                                             "Melave Malka callers"
                                             )
                                         );
            GridManager.RegisterBehavior(EmailAddress.Schema,
                                         DeletionBehavior.WithMessages(
                                             "email address from the email list",
                                             "email addresses from the email list"
                                             )
                                         );
            GridManager.RegisterBehavior(MelaveMalkaSeat.Schema,
                                         DeletionBehavior.WithMessages(
                                             "seating reservation",
                                             "seating reservations"
                                             )
                                         );
            GridManager.RegisterBehavior(MelaveMalkaInfo.Schema,
                                         DeletionBehavior.WithMessages <MelaveMalkaInfo>(
                                             singular: m => "Are you sure you want to delete the info about the " + m.Year + " Melave Malka?\r\nNo other data will be deleted.",
                                             plural: mms => "Are you sure you want to delete  info about " + mms.Count() + " Melave Malkas?\r\nNo other data will be deleted."
                                             )
                                         );
            GridManager.RegisterBehavior(MelaveMalkaInvitation.Schema,
                                         DeletionBehavior.WithMessages <MelaveMalkaInvitation>(
                                             singular: mmi => "Are you sure you want to uninvite " + mmi.Person.FullName + "?",
                                             plural: mmis => "Are you sure you want to uninvite " + mmis.Count() + " people?"
                                             )
                                         );
            GridManager.RegisterBehavior(Pledge.Schema,
                                         DeletionBehavior.WithMessages <Pledge>(
                                             singular: p => "Are you sure you want to delete this " + p.Amount.ToString("c", CultureInfo.CurrentCulture) + " pledge?",
                                             plural: pledges => "Are you sure you want to delete "
                                             + (pledges.Count().ToString(CultureInfo.InvariantCulture) + " pledges totaling "
                                                + pledges.Sum(p => p.Amount).ToString("c", CultureInfo.CurrentCulture) + "?")
                                             )
                                         );
            GridManager.RegisterBehavior(Payment.Schema,
                                         DeletionBehavior.WithMessages <Payment>(
                                             singular: p => "Are you sure you want to delete this " + p.Amount.ToString("c", CultureInfo.CurrentCulture) + " payment?",
                                             plural: payments => "Are you sure you want to delete "
                                             + (payments.Count().ToString(CultureInfo.InvariantCulture) + " payments totaling "
                                                + payments.Sum(p => p.Amount).ToString("c", CultureInfo.CurrentCulture) + "?")
                                             )
                                         );
            GridManager.RegisterBehavior(
                new TableSchema[] { Pledge.Schema, Payment.Schema },
                new AdvancedColumnsBehavior("modifier columns", new[] { "Modified", "Modifier" })
                );
            //The predicate will only be called after views are created,
            //after the client application has registered its activators
            GridManager.RegisterBehavior(
                ds => {
                var schema = TableSchema.GetSchema(ds);
                return(schema != null && AppFramework.Current.CanShowDetails(schema));
            },
                new RowDetailBehavior()
                );
        }