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

    2012년 2월 19일 일요일 오후 11: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

    2012년 2월 20일 월요일 오전 2: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

    2012년 2월 21일 화요일 오전 6: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ó 2012년 2월 21일 화요일 오전 9:43
    2012년 2월 21일 화요일 오전 9: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

    2012년 2월 21일 화요일 오전 9:42
    중재자
  • Oops!, you're right, I have not explained very well!.

    Sorry.


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

    2012년 2월 21일 화요일 오전 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

    2012년 2월 23일 목요일 오전 8: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ó 2012년 2월 24일 금요일 오후 5:47
    2012년 2월 24일 금요일 오후 5: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

    2012년 2월 26일 일요일 오전 1: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

    2012년 2월 28일 화요일 오전 7: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

    2012년 2월 29일 수요일 오전 8: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

    2012년 3월 1일 목요일 오전 9: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

    2012년 3월 1일 목요일 오후 8: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ó 2012년 3월 2일 금요일 오후 7:38
    2012년 3월 2일 금요일 오후 7:37