ListView changing datasource

8 posts, 1 answers
  1. Tino
    Tino avatar
    86 posts
    Member since:
    Jul 2017

    Posted 06 Feb 2018 Link to this post

    I'm getting an exception as follows

    System.InvalidOperationException

    "Collection was modified; enumeration operation may not execute."

     

       at System.Collections.ArrayList.ArrayListEnumeratorSimple.MoveNext()
       at Telerik.WinControls.UI.RadListViewElement.SynchronizeVisualItems()
       at Telerik.WinControls.UI.RadListView.OnGotFocus(EventArgs e)
       at System.Windows.Forms.Control.WmSetFocus(Message& m)
       at System.Windows.Forms.Control.WndProc(Message& m)
       at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
       at Telerik.WinControls.RadControl.WndProc(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
       at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

    This occurs when I change selection in my ListView after changing the datasource. So I'm reusing the ListView with different data.

    I noticed a thread that I thought might provide a clue (below) but I tried the solution but it didn't work, in fact I got the same exception in that code instead. How can I change the whole datasource in my ListView without exception? Thanks.

    https://www.telerik.com/forums/listview--detailview-item-removing

    PS: I only noticed this when attempting to highlight text (see my previous thread) and then backing out that code. But perhaps I just didn't notice the issue before.

  2. Dimitar
    Admin
    Dimitar avatar
    2839 posts

    Posted 07 Feb 2018 Link to this post

    Hi Tino,

    I am not sure how to reproduce this. I have attached my test project. Could you please check it and let me know what I need to change in order to reproduce it.

    Thank you in advance for your patience and cooperation. 

    Regards,
    Dimitar
    Progress Telerik
    Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
  3. Tino
    Tino avatar
    86 posts
    Member since:
    Jul 2017

    Posted 19 Feb 2018 in reply to Dimitar Link to this post

    I'll try, but actually I've noticed it can happen even after assigning the datasource just once.

    Also I'm using custom items and BindingList, e.g. (below, edited)

    The exception can occur after just clicking on a single item in the list. I'll try and modify your project to make it happen.

     

    _dataSource = new BindingList<MyVisualItemDef>(); // field
    SomeItems.ForEach(item => _dataSource.Add(
        new MyVisualItemDef
        {
            RuleItemId = item.RuleItemId,
            Sequence = item.Sequence,
            Name = item.Name,
            RuleItemText = GetSomeTextFor(item)
        }));
    lstvwRuleItems.DataSource = null;
    lstvwRuleItems.DataSource = _dataSource;
  4. Tino
    Tino avatar
    86 posts
    Member since:
    Jul 2017

    Posted 19 Feb 2018 Link to this post

    Please find the attached project where the issue occurs.

    See comments in method RadForm1.GetRuleItemTextFor()

  5. Tino
    Tino avatar
    86 posts
    Member since:
    Jul 2017

    Posted 19 Feb 2018 in reply to Tino Link to this post

    Keep forgetting I can only post image files... so I'll post the code in code blocks.

    class RuleVisualItem

    using System;
    using System.Drawing;
    using System.Windows.Forms;
    using Telerik.WinControls.Layouts;
    using Telerik.WinControls.UI;
     
    namespace _1152220
    {
        public class RuleVisualItem : SimpleListViewVisualItem
        {
            private RadTextBoxControlElement _idElement;
            private RadTextBoxControlElement _sequenceElement;
            private RadTextBoxControlElement _nameElement;
            private RadTextBoxControlElement _ruleTextElement;
            private StackLayoutPanel _vStackLayout;
            private StackLayoutPanel _stackLayout;
     
            protected override void CreateChildElements()
            {
                base.CreateChildElements();
     
                _stackLayout = new StackLayoutPanel
                {
                    Orientation = Orientation.Horizontal,
                    ShouldHandleMouseInput = false,
                    NotifyParentOnMouseInput = true
                };
     
                _vStackLayout = new StackLayoutPanel
                {
                    Orientation = Orientation.Vertical,
                    ShouldHandleMouseInput = false,
                    NotifyParentOnMouseInput = true
                };
     
                _sequenceElement = new RadTextBoxControlElement
                {
                    Text = "",
                    IsReadOnly = true,
                    MinSize = new Size(60, 0)
                };
                _stackLayout.Children.Add(_sequenceElement);
     
                _idElement = new RadTextBoxControlElement
                {
                    Text = "",
                    IsReadOnly = true,
                    MinSize = new Size(60, 0)
                };
     
                _stackLayout.Children.Add(_idElement);
     
                _nameElement = new RadTextBoxControlElement
                {
                    Text = "",
                    IsReadOnly = true,
                    MinSize = new Size(120, 0),
                };
                _stackLayout.Children.Add(_nameElement);
     
                _ruleTextElement = new RadTextBoxControlElement
                {
                    Text = "",
                    //TextWrap = true,
                    Multiline = true,
                    //IsReadOnly = true,
                    ShouldHandleMouseInput = true,
                    NotifyParentOnMouseInput = false
                };
     
                _vStackLayout.Children.Add(_stackLayout);
                _vStackLayout.Children.Add(_ruleTextElement);
     
                Children.Add(_vStackLayout);
            }
     
            protected override void SynchronizeProperties()
            {
                if (Data == null) return;
     
                base.SynchronizeProperties();
     
                Text = "";
                // must clear the textboxes or the info in them will be scrambled
                // https://www.telerik.com/forums/listview-data#fHqS8X47jkumon6G5VPkrQ
                _idElement.Text = "";
                _sequenceElement.Text = "";
                _nameElement.Text = "";
                _ruleTextElement.Text = "";
                _idElement.Text = Convert.ToString(Data["RuleItemId"]);
                _sequenceElement.Text = Convert.ToString(Data["Sequence"]);
                _nameElement.Text = Convert.ToString(Data["Name"]);
                var ruleItemText = Convert.ToString(Data["RuleItemText"]);
                _ruleTextElement.Text = ruleItemText;
            }
     
            protected override Type ThemeEffectiveType => typeof(SimpleListViewVisualItem);
        }
    }

     

    class RuleItemVisualItemDef

    using System.ComponentModel;
    using System.Runtime.CompilerServices;
    using _1152220.Annotations;
     
    namespace _1152220
    {
        public class RuleItemVisualItemDef : INotifyPropertyChanged
        {
            private long _ruleItemId;
            private long _sequence;
            private string _name;
            private string _ruleItemText;
     
            public long RuleItemId
            {
                get { return _ruleItemId; }
                set
                {
                    if (value == _ruleItemId) return;
                    _ruleItemId = value;
                    OnPropertyChanged();
                }
            }
     
            public long Sequence
            {
                get { return _sequence; }
                set
                {
                    if (value == _sequence) return;
                    _sequence = value;
                    OnPropertyChanged();
                }
            }
     
            public string Name
            {
                get { return _name; }
                set
                {
                    if (value == _name) return;
                    _name = value;
                    OnPropertyChanged();
                }
            }
     
            public string RuleItemText
            {
                get { return _ruleItemText; }
                set
                {
                    if (value == _ruleItemText) return;
                    _ruleItemText = value;
                    OnPropertyChanged();
                }
            }
     
            public event PropertyChangedEventHandler PropertyChanged;
     
            [NotifyPropertyChangedInvocator]
            protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
            {
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

    class RadForm1

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Text;
    using Telerik.WinControls.UI;
     
    namespace _1152220
    {
        public partial class RadForm1 : Telerik.WinControls.UI.RadForm
        {
            private BindingList<RuleItemVisualItemDef> _dataSource;
            private List<DummyData> _ruleItemDefs;
     
            public RadForm1()
            {
                InitializeComponent();
     
                lstvwRuleItems.AllowArbitraryItemHeight = true;
                lstvwRuleItems.AllowEdit = false;
                lstvwRuleItems.AllowRemove = false;
                lstvwRuleItems.ViewType = ListViewType.ListView;
     
                _ruleItemDefs = new List<DummyData>();
                for (int i = 1; i < 5; i++)
                {
                    _ruleItemDefs.Add( new DummyData
                    {
                        Name = $"Rule {i}",
                        RuleItemId = i * 10,
                        Sequence = i
                    });
                }
     
                //lstvwRuleItems.ViewType = Telerik.WinControls.UI.ListViewType.DetailsView;
                //lstvwRuleItems.DataSource = GetTable();
                SetViewContents();
            }
     
            private void SetViewContents()
            {
                txtRuleHeading.Text = GetRuleItemHeading();
     
                _dataSource = new BindingList<RuleItemVisualItemDef>();
                _ruleItemDefs.ForEach(def => _dataSource.Add(
                    new RuleItemVisualItemDef
                    {
                        RuleItemId = def.RuleItemId,
                        Sequence = def.Sequence,
                        Name = def.Name,
                        RuleItemText = GetRuleItemTextFor(def),
                    }));
                lstvwRuleItems.DataSource = null;
                lstvwRuleItems.DataSource = _dataSource;
            }
     
            private string GetRuleItemTextFor(DummyData def)
            {
                // this one usually works
                //return LoremIpsum(minWords: 0, maxWords: 10, minSentences: 1, maxSentences: 5, numParagraphs: 4);
     
                // this one usually fails (re-run the app if it doesn't)
                return LoremIpsum(minWords: 10, maxWords: 30, minSentences: 3, maxSentences: 10, numParagraphs: 4);
            }
     
            private string GetRuleItemHeading()
            {
                return "some heading";
            }
     
            //static DataTable GetTable()
            //{
            //    DataTable table = new DataTable();
            //    table.Columns.Add("bool", typeof(bool));
            //    table.Columns.Add("Drug", typeof(string));
            //    table.Columns.Add("Name", typeof(string));
            //    table.Columns.Add("Date", typeof(DateTime));
     
            //    table.Rows.Add(false, "Indocin", "David", DateTime.Now);
            //    table.Rows.Add(false, "Enebrel", "Sam", DateTime.Now);
            //    table.Rows.Add(false, "Hydralazine", "Christoff", DateTime.Now);
            //    table.Rows.Add(false, "Combivent", "Janet", DateTime.Now);
            //    table.Rows.Add(false, "Dilantin", "Melanie", DateTime.Now);
            //    return table;
            //}
     
            //private void radButton1_Click(object sender, EventArgs e)
            //{
            //    lstvwRuleItems.DataSource = null;
            //    lstvwRuleItems.DataSource = GetTable();
            //}
            string LoremIpsum(int minWords, int maxWords,
                int minSentences, int maxSentences,
                int numParagraphs)
            {
     
                var words = new[]{"lorem", "ipsum", "dolor", "sit", "amet", "consectetuer",
                    "adipiscing", "elit", "sed", "diam", "nonummy", "nibh", "euismod",
                    "tincidunt", "ut", "laoreet", "dolore", "magna", "aliquam", "erat"};
     
                var rand = new Random();
                int numSentences = rand.Next(maxSentences - minSentences)
                                   + minSentences + 1;
                int numWords = rand.Next(maxWords - minWords) + minWords + 1;
     
                StringBuilder result = new StringBuilder();
     
                for (int p = 0; p < numParagraphs; p++)
                {
                    result.Append("<p>");
                    for (int s = 0; s < numSentences; s++)
                    {
                        for (int w = 0; w < numWords; w++)
                        {
                            if (w > 0) { result.Append(" "); }
                            result.Append(words[rand.Next(words.Length)]);
                        }
                        result.Append(". ");
                    }
                    result.Append("</p>");
                }
     
                return result.ToString();
            }
     
            private void lstvwRuleItems_VisualItemCreating(object sender, Telerik.WinControls.UI.ListViewVisualItemCreatingEventArgs e)
            {
                if (this.lstvwRuleItems.ViewType == ListViewType.ListView)
                {
                    e.VisualItem = new RuleVisualItem();
                }
            }
        }
     
        internal class DummyData
        {
            public long RuleItemId { get; set; }
            public long Sequence { get; set; }
            public string Name { get; set; }
        }
    }

     

    RadForm1.Designer.cs

    namespace _1152220
    {
        partial class RadForm1
        {
            /// <summary>
            /// Required designer variable.
            /// </summary>
            private System.ComponentModel.IContainer components = null;
     
            /// <summary>
            /// Clean up any resources being used.
            /// </summary>
            /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
            protected override void Dispose(bool disposing)
            {
                if (disposing && (components != null))
                {
                    components.Dispose();
                }
                base.Dispose(disposing);
            }
     
            #region Windows Form Designer generated code
     
            /// <summary>
            /// Required method for Designer support - do not modify
            /// the contents of this method with the code editor.
            /// </summary>
            private void InitializeComponent()
            {
                this.txtRuleHeading = new Telerik.WinControls.UI.RadTextBox();
                this.lstvwRuleItems = new Telerik.WinControls.UI.RadListView();
                ((System.ComponentModel.ISupportInitialize)(this.txtRuleHeading)).BeginInit();
                ((System.ComponentModel.ISupportInitialize)(this.lstvwRuleItems)).BeginInit();
                ((System.ComponentModel.ISupportInitialize)(this)).BeginInit();
                this.SuspendLayout();
                //
                // txtRuleHeading
                //
                this.txtRuleHeading.Dock = System.Windows.Forms.DockStyle.Top;
                this.txtRuleHeading.Location = new System.Drawing.Point(0, 0);
                this.txtRuleHeading.Name = "txtRuleHeading";
                this.txtRuleHeading.Size = new System.Drawing.Size(684, 20);
                this.txtRuleHeading.TabIndex = 0;
                //
                // lstvwRuleItems
                //
                this.lstvwRuleItems.Dock = System.Windows.Forms.DockStyle.Fill;
                this.lstvwRuleItems.Location = new System.Drawing.Point(0, 20);
                this.lstvwRuleItems.Name = "lstvwRuleItems";
                this.lstvwRuleItems.Size = new System.Drawing.Size(684, 456);
                this.lstvwRuleItems.TabIndex = 1;
                this.lstvwRuleItems.VisualItemCreating += new Telerik.WinControls.UI.ListViewVisualItemCreatingEventHandler(this.lstvwRuleItems_VisualItemCreating);
                //
                // RadForm1
                //
                this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
                this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
                this.ClientSize = new System.Drawing.Size(684, 476);
                this.Controls.Add(this.lstvwRuleItems);
                this.Controls.Add(this.txtRuleHeading);
                this.Name = "RadForm1";
                //
                //
                //
                this.RootElement.ApplyShapeToControl = true;
                this.Text = "RadForm1";
                ((System.ComponentModel.ISupportInitialize)(this.txtRuleHeading)).EndInit();
                ((System.ComponentModel.ISupportInitialize)(this.lstvwRuleItems)).EndInit();
                ((System.ComponentModel.ISupportInitialize)(this)).EndInit();
                this.ResumeLayout(false);
                this.PerformLayout();
     
            }
     
            #endregion
     
            private Telerik.WinControls.UI.RadTextBox txtRuleHeading;
            private Telerik.WinControls.UI.RadListView lstvwRuleItems;
        }
    }
  6. Answer
    Dimitar
    Admin
    Dimitar avatar
    2839 posts

    Posted 20 Feb 2018 Link to this post

    Hi Tino,

    I was able to reproduce this exception. It is caused by an issue in our implementation. I have logged this issue on our Feedback Portal. You can track its progress, subscribe to status changes and add your comment to it here. I have also updated your Telerik Points.

    You need to inherit the control in order to override the following methods and workaround this issue:
    class MyListView : RadListView
    {
        protected override RadListViewElement CreateListViewElement()
        {
            return new MyListViewElement();
        }
    }
    class MyListViewElement : RadListViewElement
    {
        protected override Type ThemeEffectiveType => typeof(RadListViewElement);
        public override void SynchronizeVisualItems()
        {
            
            for (int i = 0; i < this.ViewElement.ViewElement.Children.Count; i++)
            {
                BaseListViewVisualItem visualItem = (BaseListViewVisualItem)this.ViewElement.ViewElement.Children[i];
                visualItem.Synchronize();
            }
     
            this.Invalidate();
        }
    }

    Should you have any other questions do not hesitate to ask.

    Regards,
    Dimitar
    Progress Telerik
    Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
  7. Tino
    Tino avatar
    86 posts
    Member since:
    Jul 2017

    Posted 20 Feb 2018 in reply to Dimitar Link to this post

    Thanks for the workaround, it seems to have done the trick.
  8. Dimitar
    Admin
    Dimitar avatar
    2839 posts

    Posted 21 Feb 2018 Link to this post

    Hi Tino,

    I am glad that this is working fine now. Do not hesitate to contact us if you have other questions.

    Regards,
    Dimitar
    Progress Telerik
    Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
Back to Top