This is a migrated thread and some comments may be shown as answers.

ListView changing datasource

11 Answers 441 Views
ListView
This is a migrated thread and some comments may be shown as answers.
Tino
Top achievements
Rank 1
Tino asked on 06 Feb 2018, 11:21 PM

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.

11 Answers, 1 is accepted

Sort by
0
Dimitar
Telerik team
answered on 07 Feb 2018, 07:30 AM
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.
0
Tino
Top achievements
Rank 1
answered on 19 Feb 2018, 11:52 PM

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;
0
Tino
Top achievements
Rank 1
answered on 20 Feb 2018, 12:42 AM

Please find the attached project where the issue occurs.

See comments in method RadForm1.GetRuleItemTextFor()

0
Tino
Top achievements
Rank 1
answered on 20 Feb 2018, 12:57 AM

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;
    }
}
0
Accepted
Dimitar
Telerik team
answered on 20 Feb 2018, 10:19 AM
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.
0
Tino
Top achievements
Rank 1
answered on 20 Feb 2018, 09:26 PM
Thanks for the workaround, it seems to have done the trick.
0
Dimitar
Telerik team
answered on 21 Feb 2018, 08:31 AM
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.
0
MORDECHAI
Top achievements
Rank 1
answered on 08 Jun 2020, 03:58 PM
I've been struggling with this issue in RadListControl for quite. Since it happens by me in unpredictable patterns I can't tell at the moment if this workaround (with minor changes to adapt to RadListControl) fixes it, but it should, given it's a foreach issue in RadListElement:2270
0
Dess | Tech Support Engineer, Principal
Telerik team
answered on 10 Jun 2020, 08:45 AM

Hello, Mordechai, 

According to the provided brief information, it is not clear whether you are experiencing any issues with RadListControl in the latest version of the Telerik UI for WinForms suite.

I would like to note that the previously referred feedback item has already been fixed. Hence, you are not expected to experience any undesired behavior in the latest version. 

However, if you encounter any further difficulties, feel free to submit a support ticket from your Telerik account and provide as much information as possible about the precise case. A sample project would be also greatly appreciated. Thus, we would be able to investigate the precise case and provide further assistance. Thank you in advance. 

I hope this information helps. If you need any further assistance please don't hesitate to contact me. 

Regards,
Dess | Tech Support Engineer, Sr.
Progress Telerik

Progress is here for your business, like always. Read more about the measures we are taking to ensure business continuity and help fight the COVID-19 pandemic.
Our thoughts here at Progress are with those affected by the outbreak.
0
MORDECHAI
Top achievements
Rank 1
answered on 10 Jun 2020, 02:40 PM

Hi Dess,

 

Firstly, your workaround mentioned earlier for RadListView I followed for RadListControl did in fact fix our issue. Inspecting the Telerik source I did notice the fix in RadListView but not in RadListControl which still uses a foreach loop.

 

Weirdly enough, the fix unexpectedly affected how the fonts worked in RadTextBoxControlElement. Before the change I had to use the CustomFont to change the font, but after that change I could just use Font

 

Sorry, I'm not very good at creating demo projects, here's my code:

class RadListControlMod : RadListControl
{
    protected override RadListElement CreateListElement()
    {
        return new RadListElementMod();
    }
}
 
class RadListElementMod : RadListElement
{
 
    protected override Type ThemeEffectiveType => typeof(RadListElement);
    protected override void SynchronizeVisualItems()
    {
 
        for (var i = 0; i < ViewElement.Children.Count; i++)
        {
            var visualItem = (RadListVisualItem)ViewElement.Children[i];
            visualItem.Synchronize();
        }
 
        Invalidate();
    }
}
0
Dess | Tech Support Engineer, Principal
Telerik team
answered on 12 Jun 2020, 11:32 AM

Hello, Mordechai,  

It is still not clear to me what is the exact setup that you have on your end with RadListControl and and what is the exact problem that you are facing. Could you please elaborate?

According to the provided information, it seems that you create a custom RadListControl which in the RadListElement.SynchronizeVisualItems method forces synchronizing the visual items. 
Actually, the default implementation executes a similar action. Here is the original source code of the RadListElement

        protected virtual void SynchronizeVisualItems()
        {
            foreach (RadListVisualItem item in this.ViewElement.Children)
            {
                item.Synchronize();
            }

            this.Invalidate();
        }

This is a code snippet from the latest official version. I am not sure which is the version you are using in your project. Have you tried the default behavior in the latest version? Are you still experiencing any issues? 

I would kindly ask you to submit a support ticket from your account and provide a sample project demonstrating the undesired behavior that you are facing. Thus, we would be able to make an adequate analysis of the precise case and think about an appropriate solution. Thank you in advance.

I am looking forward to your reply.

Regards,
Dess | Tech Support Engineer, Sr.
Progress Telerik

Progress is here for your business, like always. Read more about the measures we are taking to ensure business continuity and help fight the COVID-19 pandemic.
Our thoughts here at Progress are with those affected by the outbreak.
Tags
ListView
Asked by
Tino
Top achievements
Rank 1
Answers by
Dimitar
Telerik team
Tino
Top achievements
Rank 1
MORDECHAI
Top achievements
Rank 1
Dess | Tech Support Engineer, Principal
Telerik team
Share this question
or