Hi

I tried searching for the solution to my problem but could not find a
solution that I could use.

My problem is that I want to show the child collections (the many part
of one to many relation) in a grid and let the user do add/delete/edit
operation via the grid itself. So far I have no problems. The example
can be taken as invoice header and invoice details being shown in the
same screen in a winform application.

All I want to do is to sort the items in the child collection (the
invoice details). I do not want any too flexible idea just I want to
be able to sort by say 'ToString()' or some property of the items in
the child collection.

I tried using ISet with Sort = "namespace.ItemComparer, namespace" in
HasMany attribute and the data comes out to be sorted. But now lose
tracking of items which are being deleted from the collection.
Currently I have wrapper around the IList (for child collection) which
manages to call .Delete() on the object being removed.

So all in all, I am looking for iea on how to implement custom
collection with facility to sort and also track items which are
removed so that they may be deleted from database.

The sample of code I am using is as following

        private IList<InvoiceDetail> _InvoiceDetailsInternal;
        [HasMany(typeof(InvoiceDetail), ColumnKey="invoice_header_id",
Lazy=true, Fetch=FetchEnum.Select, RelationType = RelationType.Guess,
Inverse=true, Cascade = ManyRelationCascadeEnum.All, Cache =
CacheEnum.ReadWrite, CacheRegion = "CachedData", CollectionType =
typeof(DomainCollectionFactory<InvoiceDetail>))]
        protected virtual IList<InvoiceDetail> InvoiceDetailsInternal
        {
            get
            {
               if(_InvoiceDetailsInternal == null)
                  InvoiceDetailsInternal = new List<InvoiceDetail>();
               return _InvoiceDetailsInternal ;
            }
            set
            {
                _InvoiceDetailsInternal = value;
                _InvoiceDetails = new
GSBindingListSortable<InvoiceDetail>(value);
                RegisterForChangeTracking(_InvoiceDetails);
             }
        }
        private GSBindingListSortable<InvoiceDetail> _InvoiceDetails;
        public virtual GSBindingListSortable<InvoiceDetail>
InvoiceDetails
        {
            get
            {
                if(_InvoiceDetails == null)
                    InvoiceDetailsInternal = new List<InvoiceDetail>
();
                return _InvoiceDetails;
            }
        }

Here GSBindingListSortable is a derivative of BindingList<T> and
calls .Delete() for the object that is being removed from the list.

Also the code for custom collection is attached. I found it on
internet somewhere (I forgot the link).

using System.Collections.Generic;
using System.Collections.Specialized;
using System.Collections;
using NHibernate.Collection.Generic;
using NHibernate.UserTypes;
using NHibernate.Engine;
using NHibernate.Persister.Collection;
using NHibernate.Collection;
using GSLibrary;
using System.ComponentModel;

namespace GSSalesManager
{
    public interface IDomainCollection<T> : INotifyCollectionChanged,
IList<T>
                where T : class
    {
    }

    public class TransientDomainCollection<T> : List<T>,
IDomainCollection<T>
        where T : class
    {
        #region INotifyCollectionChanged Members
        public event NotifyCollectionChangedEventHandler
CollectionChanged;
        /// <summary>
        /// Fires the <see cref="CollectionChanged"/> event to
indicate an item has been
        /// added to the end of the collection.
        /// </summary>
        /// <param name="item">Item added to the collection.</param>
        protected void OnItemAdded(T item)
        {
            if (this.CollectionChanged != null)
            {
                this.CollectionChanged(this, new
NotifyCollectionChangedEventArgs(
 
NotifyCollectionChangedAction.Add, item, this.Count - 1));
            }
        }
        /// <summary>
        /// Fires the <see cref="CollectionChanged"/> event to
indicate the collection
        /// has been reset.  This is used when the collection has been
cleared or
        /// entirely replaced.
        /// </summary>
        protected void OnCollectionReset()
        {
            if (this.CollectionChanged != null)
            {
                this.CollectionChanged(this, new
NotifyCollectionChangedEventArgs(
 
NotifyCollectionChangedAction.Reset));
            }
        }
        /// <summary>
        /// Fires the <see cref="CollectionChanged"/> event to
indicate an item has
        /// been inserted into the collection at the specified index.
        /// </summary>
        /// <param name="index">Index the item has been inserted at.</
param>
        /// <param name="item">Item inserted into the collection.</
param>
        protected void OnItemInserted(int index, T item)
        {
            if (this.CollectionChanged != null)
            {
                this.CollectionChanged(this, new
NotifyCollectionChangedEventArgs(
 
NotifyCollectionChangedAction.Add, item, index));
            }
        }
        /// <summary>
        /// Fires the <see cref="CollectionChanged"/> event to
indicate an item has
        /// been removed from the collection at the specified index.
        /// </summary>
        /// <param name="item">Item removed from the collection.</
param>
        /// <param name="index">Index the item has been removed from.</
param>
        protected void OnItemRemoved(T item, int index)
        {
            if (this.CollectionChanged != null)
            {
                this.CollectionChanged(this, new
NotifyCollectionChangedEventArgs(
 
NotifyCollectionChangedAction.Remove, item, index));
            }
        }
        #endregion

        /// <summary>
        /// we need to re-implement the IList methods to support
observability
        /// </summary>
        /// <param name="item"></param>
        #region IList<T> members
        public new void Add(T item)
        {
            base.Add(item);
            this.OnItemAdded(item);
        }
        public new void Clear()
        {
            base.Clear();
            this.OnCollectionReset();
        }
        public new void Insert(int index, T item)
        {
            base.Insert(index, item);
            this.OnItemInserted(index, item);
        }
        public new bool Remove(T item)
        {
            int index = this.IndexOf(item);
            bool result = base.Remove(item);
            this.OnItemRemoved(item, index);
            return result;
        }
        public new void RemoveAt(int index)
        {
            T item = this[index];
            base.RemoveAt(index);
            this.OnItemRemoved(item, index);
        }
        #endregion
    }

    public class PersistentDomainCollection<T> :
PersistentGenericBag<T>, IDomainCollection<T>
        where T : class
    {
        #region constructors
        public PersistentDomainCollection(ISessionImplementor session,
IList<T> coll)
            : base(session, coll)
        {
        }
        public PersistentDomainCollection(ISessionImplementor session)
            : base(session)
        {
        }
        #endregion

        #region INotifyCollectionChanged Members
        public event NotifyCollectionChangedEventHandler
CollectionChanged;
        /// <summary>
        /// Fires the <see cref="CollectionChanged"/> event to
indicate an item has been
        /// added to the end of the collection.
        /// </summary>
        /// <param name="item">Item added to the collection.</param>
        protected void OnItemAdded(T item)
        {
            if (this.CollectionChanged != null)
            {
                this.CollectionChanged(this, new
NotifyCollectionChangedEventArgs(
 
NotifyCollectionChangedAction.Add, item, this.Count - 1));
            }
        }
        /// <summary>
        /// Fires the <see cref="CollectionChanged"/> event to
indicate the collection
        /// has been reset.  This is used when the collection has been
cleared or
        /// entirely replaced.
        /// </summary>
        protected void OnCollectionReset()
        {
            if (this.CollectionChanged != null)
            {
                this.CollectionChanged(this, new
NotifyCollectionChangedEventArgs(
 
NotifyCollectionChangedAction.Reset));
            }
        }
        /// <summary>
        /// Fires the <see cref="CollectionChanged"/> event to
indicate an item has
        /// been inserted into the collection at the specified index.
        /// </summary>
        /// <param name="index">Index the item has been inserted at.</
param>
        /// <param name="item">Item inserted into the collection.</
param>
        protected void OnItemInserted(int index, T item)
        {
            if (this.CollectionChanged != null)
            {
                this.CollectionChanged(this, new
NotifyCollectionChangedEventArgs(
 
NotifyCollectionChangedAction.Add, item, index));
            }
        }
        /// <summary>
        /// Fires the <see cref="CollectionChanged"/> event to
indicate an item has
        /// been removed from the collection at the specified index.
        /// </summary>
        /// <param name="item">Item removed from the collection.</
param>
        /// <param name="index">Index the item has been removed from.</
param>
        protected void OnItemRemoved(T item, int index)
        {
            if (this.CollectionChanged != null)
            {
                this.CollectionChanged(this, new
NotifyCollectionChangedEventArgs(
 
NotifyCollectionChangedAction.Remove, item, index));
            }
        }
        #endregion

        /// <summary>
        /// we need to re-implement the IList methods to support
observability
        /// </summary>
        /// <param name="item"></param>
        #region IList<T> members
        public void Add(T item)
        {
            base.Add(item);
            this.OnItemAdded(item);
        }
        public new void Clear()
        {
            base.Clear();
            this.OnCollectionReset();
        }
        public void Insert(int index, T item)
        {
            base.Insert(index, item);
            this.OnItemInserted(index, item);
        }
        public void Remove(T item)
        {
            int index = this.IndexOf(item);
            base.Remove(item);
            this.OnItemRemoved(item, index);
        }
        public new void RemoveAt(int index)
        {
            var item = this[index] as T;
            base.RemoveAt(index);
            this.OnItemRemoved(item, index);
        }
        #endregion

    }

    public class DomainCollectionFactory<T> : IUserCollectionType
        where T : class
    {
        #region IUserCollectionType Members
        public IPersistentCollection Instantiate(ISessionImplementor
session, ICollectionPersister persister)
        {
            return new PersistentDomainCollection<T>(session);
        }
        public IPersistentCollection Wrap(ISessionImplementor session,
object collection)
        {
            return new PersistentDomainCollection<T>(session,
collection as IList<T>);
        }
        public object Instantiate()
        {
            return new TransientDomainCollection<T>();
        }

        public object Instantiate(int anticipatedSize)
        {
            return new TransientDomainCollection<T>();
        }

        public IEnumerable GetElements(object collection)
        {
            return (IEnumerable)collection;
        }
        public bool Contains(object collection, object entity)
        {
            return ((IList)collection).Contains(entity);
        }
        public object IndexOf(object collection, object entity)
        {
            return ((IList)collection).IndexOf(entity);
        }
        public object ReplaceElements(object original, object target,
ICollectionPersister persister,
                                      object owner, IDictionary
copyCache, ISessionImplementor session)
        {
            IList result = (IList)target;
            result.Clear();
            foreach (object o in ((IEnumerable)original))
            {
                result.Add(o);
            }
            return result;
        }
        #endregion
    }
}

--

You received this message because you are subscribed to the Google Groups 
"Castle Project Users" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/castle-project-users?hl=en.


Reply via email to