none
iEditableObject class with a List type property

    שאלה

  • Hi,

    I want bind to datagridview an object where one of their properties is of type List. This object implements IEditableObject but the compiler don't allow me to bind.

    I put an example:

    public class Object1 : IEditableObject
    {
    private int p_Id;
    private List<Decimal> p_DecimalList;
    }
    
    public class Object1List : BindingList<Object1>
    {
    }
    
    public partial class Form1 : Form
    {
    bindingsource1.DataSource = Object1List;
    dataGridView1.DataSource = bindingsource1;
    }

    Regards.


    Albert Gassó
    Ingeniero Técnico en Informática
    Computer Software Engineer

    יום ראשון 19 פברואר 2012 23:15

כל התגובות

  • Binding requires public properties.  But in case that is not the problem, you should always post your question with the error messages that you get.

    Jose R. MCP

    יום שני 20 פברואר 2012 02:08
  • Hi Albert,
    I agree with Jose and if your object implements IEditableObject interface, you need to implements IEditableObject.BeginEdit Method, IEditableObject.CancelEdit Method and IEditableObject.EndEdit Method.
    The following link provides a simple implementation of the IEditableObject interface. 

    http://msdn.microsoft.com/en-us/library/system.componentmodel.ieditableobject.aspx

    If there is anything unclear, please let us know.

    Best Regarsd,


    Bob Wu [MSFT]
    MSDN Community Support | Feedback to us

    יום שלישי 21 פברואר 2012 06:40
    מנחה דיון
  • Thanks you all, for your answers,

    webJose, I don't have any error message, directly the compiler go out without message.

    Bob, I know that if I use IEditableObject i must implement three methods (BeginEdit, CancelEdit, EndEdit), but I haven't put this methods in my example for simplifying.

    I would add a comment, I use a List of integers because my goal is get an object with a dynamic property. If I use a List of integers, I can assign its size in run time, otherwise I must define the size of list in design time.

    Regards


    Albert Gassó
    Ingeniero Técnico en Informática
    Computer Software Engineer


    • נערך על-ידי Albert Gassó יום שלישי 21 פברואר 2012 09:43
    יום שלישי 21 פברואר 2012 09:39
  • So what do you mean by “ but the compiler don't allow me to bind.”;
    Best Regards,

    Bob Wu [MSFT]
    MSDN Community Support | Feedback to us

    יום שלישי 21 פברואר 2012 09:42
    מנחה דיון
  • Oops!, you're right, I have not explained very well!.

    Sorry.


    Albert Gassó
    Ingeniero Técnico en Informática
    Computer Software Engineer

    יום שלישי 21 פברואר 2012 11:40
  • Hi Albert,
    Could you please give the following information?
    Can you build the application?
    Can you run the application?
    Does the data displayed correctly?
    You said that ”the compiler don't allow me to bind.”, so what does it shows? If nothing (error message or anything) shows, how can you know “the compiler don't allow me to bind”?
    In addition, if you can share the code with us, it will help to solve this issue.
    Best Regards

    Bob Wu [MSFT]
    MSDN Community Support | Feedback to us

    יום חמישי 23 פברואר 2012 08:26
    מנחה דיון
  • I have researched a little more, and I have seen that I have an error. But still, don't appear any error, and when I run application in DataGridView I don't see the column. Maybe by the following piece of code belonging to iEditableObject overriden methods:

            #region IEditableObject Members
    
            public virtual void BeginEdit()
            {
                if (m_Editing == false)
                {
                    m_Editing = true;
                    m_OldValues = new Hashtable();
                    PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(this);
                    foreach (PropertyDescriptor property in properties)
                    {
                        m_OldValues.Add(property, property.GetValue(this));
                    }
                }
            }
    
    
            public virtual void CancelEdit()
            {
                if (m_Editing == true)
                {
                    // Undo edit changes
                    PropertyDescriptor property = null;
                    foreach (DictionaryEntry entry in m_OldValues)
                    {
                        property = (PropertyDescriptor)entry.Key;
                        property.SetValue(this, entry.Value);
                    }
    
                    // Clean up
                    m_OldValues = null;
                    m_Editing = false;
                }
            }
    
    
            public virtual void EndEdit()
            {
                if (m_Editing == true)
                {
                    // Clean up
                    m_OldValues = null;
                    m_Editing = false;
                }
            }
    
            #endregion

    At line  

    m_OldValues.Add(property, property.GetValue(this)); 

    property.GetValue(this) where on property is  List<Decimal> I get (Count = number of elements of the list).

    Thanks


    Albert Gassó
    Ingeniero Técnico en Informática
    Computer Software Engineer
    Barcelona




    • נערך על-ידי Albert Gassó יום שישי 24 פברואר 2012 17:47
    יום שישי 24 פברואר 2012 17:39
  • I just want to do that they ask in this thread:

    http://social.msdn.microsoft.com/Forums/en-US/csharplanguage/thread/2e8f6214-e242-4a81-b49e-50bce1ee3bfe

    Regards


    Albert Gassó
    Ingeniero Técnico en Informática
    Computer Software Engineer
    Barcelona

    יום ראשון 26 פברואר 2012 01:19
  • Hi Albert,
    The link makes me more confused about your requirement. What are you trying to do?
    Do you trying to bind the DataGridView to the List<Decimal> of the Object1 class? Suppose List<Decimal> has three Decimal, the bound DataGridView will have three columns?
    Best Regards,

    Bob Wu [MSFT]
    MSDN Community Support | Feedback to us

    יום שלישי 28 פברואר 2012 07:32
    מנחה דיון
  • Hi Bob,

    I try to bind a custom object to datagridview. My custom object have a "normal" properties and a list of types, or list of objects property. Can be either (list of types, or list of objects). In my example, I put a list of types because I thought it would be clearer and the target was the same. I put a clarifying example:

    public class InvoiceLine : FSBindingItem
    {
            private string p_IdProduct;
            private string p_IdInvoice;
            private int p_LineNumber; 
            private List<UnitsSize> p_UnitsSizeList;
    
            public string IdProduct
            {
                get { return p_IdProduct; }
                set { p_IdProduct = value; }
            }
    
            public string IdInvoice
            {
                get { return p_IdInvoice; }
                set { p_IdInvoice = value; }
            }
    
            public int LineNumber
            {
                get { return p_LineNumber; }
                set { p_LineNumber = value; }
            }
    
            public List<UnitsSize> UnitsSizeList
            {
                get { return p_UnitsSizeList; }
                set { p_UnitsSizeList = value; }
            }
    }
    
    public class UnitsSize : FSBindingItem
    {
            private string p_IdSize;
            private decimal p_UnitsPerSize;
    
            public string IdSize
            {
                get { return p_IdSize; }
                set { p_IdSize = value; }
            }
    
            public decimal UnitsPerSize
            {
                get { return p_UnitsPerSize; }
                set { p_UnitsPerSize = value; }
            }
    }
    
    public class InvoiceLineList : BindingList<InvoiceLine>
    {
    }
    
    public partial class Form1 : Form
    {
            bindingsource1.DataSource = InvoiceLineList;
            dataGridView1.DataSource = bindingsource1;
    }
    
    public abstract class FSBindingItem : IEditableObject
    {
            protected bool m_Editing = false;
            protected Hashtable m_OldValues;
    
            #region Constructor
    
            public FSBindingItem()
            {
            }
    
            public virtual void BeginEdit()
            {
                if (m_Editing == false)
                {
                    m_Editing = true;
                    m_OldValues = new Hashtable();
                    PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(this);
                    foreach (PropertyDescriptor property in properties)
                    {
                        m_OldValues.Add(property, property.GetValue(this));
                    }
                }
            }
    
    
            public virtual void CancelEdit()
            {
                if (m_Editing == true)
                {
                    // Undo edit changes
                    PropertyDescriptor property = null;
                    foreach (DictionaryEntry entry in m_OldValues)
                    {
                        property = (PropertyDescriptor)entry.Key;
                        property.SetValue(this, entry.Value);
                    }
    
                    // Clean up
                    m_OldValues = null;
                    m_Editing = false;
                }
            }
    
    
            public virtual void EndEdit()
            {
                if (m_Editing == true)
                {
                    // Clean up
                    m_OldValues = null;
                    m_Editing = false;
                }
            }
    }
    
    public class FSBindingList<T> : BindingList<T>
    {
            private bool p_isSorted;
            private PropertyDescriptor p_sortProperty;
            private ListSortDirection p_sortDirection;
    
            #endregion
    
            #endregion
    
            #region Properties
    
            #region Sorting Properties
    
            protected override bool IsSortedCore
            {
                get { return p_isSorted; }
            }
    
            protected override bool SupportsSortingCore
            {
                get { return true; }
            }
    
            protected override ListSortDirection SortDirectionCore
            {
                get { return p_sortDirection; }
            }
    
            protected override PropertyDescriptor SortPropertyCore
            {
                get { return p_sortProperty; }
            }
    
            #endregion
    
            #region Searching Properties
    
            protected override bool SupportsSearchingCore
            {
                get { return true; }
            }
    
            #endregion
    
            #endregion
    
            #region Methods
    
            #region Sorting Methods
    
            protected override void ApplySortCore(PropertyDescriptor property, ListSortDirection direction)
            {
                // Get list to sort
                // Note: this.Items is t non-sortable ICollection<T>
                List<T> items = this.Items as List<T>;
    
                // Apply and set the sort, if items to sort
                if (items != null)
                {
                    FSPropertyComparer<T> pc = new FSPropertyComparer<T>(property, direction);
                    //QuickSort algorithm
                    items.Sort(pc);
                    p_isSorted = true;
                }
                else
                {
                    p_isSorted = false;
                }
    
                p_sortProperty = property;
                p_sortDirection = direction;
    
                this.OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
            }
    
            protected override void RemoveSortCore()
            {
                p_isSorted = false;
                this.OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
            }
    
            public void Sort(PropertyDescriptor property, ListSortDirection direction)
            {
                this.ApplySortCore(property, direction);
            }
    
            #endregion
    
            #region Searching Methods
    
            /// <summary>
            /// Searches an FSBindingList for a particular item.
            /// </summary>
            /// <param name="property">The property to search.</param>
            /// <param name="key">The value to find.</param>
            /// <returns>The collection index of the found item.</returns>
            protected override int FindCore(PropertyDescriptor property, object key)
            {
                // Exit if no property specified
                if (property == null) return -1;
    
                // Get list to search
                List<T> items = this.Items as List<T>;
    
                // Traverse list for value
                foreach (T item in items)
                {
                    // Test column search value
                    string value = (string)property.GetValue(item);
    
                    // If value is the search value, return the index of the data item
                    if (((string)key).Equals(value)) return IndexOf(item);
                }
                return -1;
            }
    
            #endregion
    
            #region Persistence Methods
    
            /* These methods are used to serialize a collection to a file, 
             * and to deserialize it from a file. They are intended for use 
             * with standalone files, rather than a database. */
    
            /* NOTE: BindingList<T> is not serializable, but List<T> is. 
             * So, we cast the list to (List<T>) for loads and saves. */
    
            /// <summary>
            /// Loads a collection from a serialized file.
            /// </summary>
            /// <param name="filename">The file path of the file to open.</param>
            public void Load(string filename)
            {
                this.ClearItems();
    
                if (File.Exists(filename))
                {
                    BinaryFormatter formatter = new BinaryFormatter();
                    using (FileStream stream = new FileStream(filename, FileMode.Open))
                    {
                        // Deserialize data list items
                        ((List<T>)this.Items).AddRange((IEnumerable<T>)formatter.Deserialize(stream));
                    }
                }
    
                // Let bound controls know they should refresh their views
                this.OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
            }
    
            /// <summary>
            /// Saves a collection to a serialized file.
            /// </summary>
            /// <param name="filename">The file path of the file to save.</param>
            public void Save(string filename)
            {
                BinaryFormatter formatter = new BinaryFormatter();
                using (FileStream stream = new FileStream(filename, FileMode.Create))
                {
                    // Serialize data list items
                    formatter.Serialize(stream, (List<T>)this.Items);
                }
            }
    
            #endregion
    
            #region Replace Methods
    
            public void Replace(int index, T item)
            {
                this.SetItem(index, item);
            }
    
            #endregion
        }
    }

    I hope I have clarifying my problem.

    Regards


    Albert Gassó
    Ingeniero Técnico en Informática
    Computer Software Engineer
    Barcelona

    יום רביעי 29 פברואר 2012 08:00
  • Hi Albert,
    I’m afraid I still have the same question?
    InvoiceLine class have four properties: IdProduct,IdInvoice,LineNumber and List<UnitsSize> UnitsSizeList. After binding an instance of InvoiceLineList, how many columns should DataGridView have?
    IdProduct,IdInvoice,LineNumber and IdSize,UnitsPerSize or IdProduct,IdInvoice,LineNumber and  numbers of IdSize,UnitsPerSize column?
    Could you please help us picture the DataGridView and the Data in each cell?
    Best Regards,


    Bob Wu [MSFT]
    MSDN Community Support | Feedback to us

    יום חמישי 01 מרץ 2012 09:19
    מנחה דיון
  • Hi Bob,

    I am attaching a picture to clarify what I seek:

    The columns Units per Size 7, Units per Size 8.5, etc... are a property of object UnitsSize.

    This picture shows a lnvoiceLine with a properties:

    IdInvoice, Date, LineNumber, IdProduct, Description, IdColor, List<UnitsSize> UnitsSizeList

    Where I use the property "UnitsPerSize" of each UnitsSize object of list, which this list is inside of InvoiceLine object.

    Regards.


    Albert Gassó
    Ingeniero Técnico en Informática
    Computer Software Engineer
    Barcelona

    יום חמישי 01 מרץ 2012 20:06
  • I try this code, but it doesn't do that I want, because I have a List of UnitsSize objects:

        public class InvoiceLineDescriptor : CustomTypeDescriptor
        {
            public InvoiceLineDescriptor(ICustomTypeDescriptor parent)
                : base(parent)
            {
            }
    
            public override PropertyDescriptorCollection GetProperties()
            {
                // get the attributes of InvoiceLine
                PropertyDescriptorCollection cols = base.GetProperties();
    
                PropertyDescriptor unitsSizePD = cols["UnitsSize"];
    
                PropertyDescriptorCollection p_size_child = unitsSizePD.GetChildProperties();
    
                PropertyDescriptor[] array = new PropertyDescriptor[cols.Count + 2];
    
                cols.CopyTo(array, 0);
                
                array[cols.Count] = new SubPropertyDescriptor(unitsSizePD, p_talla_child["IdSize"], "IdSize");
                array[cols.Count + 1] = new SubPropertyDescriptor(unitsSizePD, p_talla_child["Units"], "Units");
    
                PropertyDescriptorCollection newcols = new PropertyDescriptorCollection(array);
                return newcols;
            }
    
            public override PropertyDescriptorCollection GetProperties(Attribute[] attributes)
            {
                return (GetProperties());
            }
        }


    Albert Gassó
    Ingeniero Técnico en Informática
    Computer Software Engineer
    Barcelona


    • נערך על-ידי Albert Gassó יום שישי 02 מרץ 2012 19:38
    יום שישי 02 מרץ 2012 19:37