0

我在使用默认 CollectionEditor 时遇到了这个问题。

当我将项目添加到集合编辑器时,我将项目显示为用户控件上的矩形。但是,当我删除已经存在的项目时,预览不会更新,直到我单击“确定”或“添加”按钮。

我在下面提供了相同的代码。

制作步骤:

  1. 将控件添加到 from。
  2. 通过打开 CollectionEditor 并添加(比如 3. 项目。(你看到项目被添加到控件)来编辑控件的 Collection 属性。预览得到很好的更新。
  3. 现在单击确定按钮。
  4. 重新打开 CollectionEditor 并尝试删除现有项目。我希望这些项目在预览中被删除。但删除的项目仍保留在控件上,直到我单击“添加”按钮或“确定”按钮。:(

这是 CollectionEditor 类中的错误吗?

源代码:

TestCollectionClass.cs

using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing.Design;
using System.Globalization;
using System.Security.Permissions;
using System.Windows.Forms;
using System.Drawing;

namespace TestCollectionEditor
{
    using T = TestComponent;

    [
        Editor("", typeof(UITypeEditor)),
        ListBindable(false)
    ]
    public class TestCollectionClass : IList, ICollection, IEnumerable
    {
        private IList _list;
        private Size _renderFrame;

        public delegate void CollectionChangeEventHandler(object sender, EventArgs e);
        public event CollectionChangeEventHandler _onCollectionChanged;
        public event CollectionChangeEventHandler CollectionChanged
        {
            add
            {
                lock (this)
                {
                    _onCollectionChanged += value;
                }
            }
            remove
            {
                lock (this)
                {
                    _onCollectionChanged -= value;
                }
            }
        }

        protected virtual void OnCollectionChanged(EventArgs e)
        {
            if (_onCollectionChanged != null)
            {
                _onCollectionChanged(this, e);
            }
        }

        public TestCollectionClass(Size size)
        {
            _list = new ArrayList();
            _renderFrame = size;
        }

        public TestCollectionClass(T[] item)
            : this(new Size(100, 100))
        {
            AddRange(item);
        }

        public TestCollectionClass(TestCollectionClass item)
            : this(new Size(100, 100))
        {
            AddRange(item);
        }

        public override string ToString()
        {
            return String.Format(CultureInfo.CurrentCulture, "{0}: Count={1}", GetType().Name, Count);
        }

        public T this[int index]
        {
            get { return (T)_list[index]; }
            set
            {
                _list[index] = value;
            }
        }

        object IList.this[int index]
        {
            get { return this[index]; }
            set
            {
                T item = value as T;
                if (item == null)
                    throw GetInvalidTypeException(value);

                this[index] = item;
            }
        }

        public int Add(T item)
        {
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }

            int i = _list.Add(item);
            OnCollectionChanged(new EventArgs());
            return i;
        }

        int IList.Add(object item)
        {
            T value = item as T;
            if (value == null)
                throw GetInvalidTypeException(item);

            return Add(value);
        }

        public void AddRange(T[] item)
        {
            if (item == null)
                throw new ArgumentNullException("item");

            foreach (T current in item)
                Add(current);
        }

        public void AddRange(TestCollectionClass item)
        {
            if (item == null)
                throw new ArgumentNullException("item");

            foreach (T current in item)
                Add(current);
        }

        public void Clear()
        {
            _list.Clear();
            OnCollectionChanged(new EventArgs());
        }

        public int Count
        {
            get { return _list.Count; }
        }

        public bool Contains(T item)
        {
            if (item == null)
            {
                return false;
            }

            return _list.Contains(item);
        }

        bool IList.Contains(object item)
        {
            T value = item as T;
            if (value == null)
                throw GetInvalidTypeException(item);

            return Contains(value);
        }

        public void CopyTo(T[] array, int index)
        {
            ICollection collection = this as ICollection;
            collection.CopyTo(array, index);
        }

        void ICollection.CopyTo(System.Array array, int index)
        {
            if (array == null)
            {
                throw new ArgumentNullException("array");
            }

            _list.CopyTo(array, index);
        }

        public int IndexOf(T item)
        {
            if (item == null)
            {
                return -1;
            }

            return _list.IndexOf(item);
        }

        int IList.IndexOf(object item)
        {
            T value = item as T;
            if (value == null)
                throw GetInvalidTypeException(item);

            return IndexOf(value);
        }

        public void Insert(int index, T item)
        {
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }

            _list.Insert(index, item);
            OnCollectionChanged(new EventArgs());
        }

        void IList.Insert(int index, object item)
        {
            T value = item as T;
            if (value == null)
                throw GetInvalidTypeException(item);

            Insert(index, value);
        }

        bool ICollection.IsSynchronized
        {
            get { return IsSynchronized; }
        }

        protected bool IsSynchronized
        {
            get { return _list.IsSynchronized; }
        }

        bool IList.IsFixedSize
        {
            get { return IsFixedSize; }
        }

        protected bool IsFixedSize
        {
            get { return _list.IsFixedSize; }
        }

        bool IList.IsReadOnly
        {
            get { return IsReadOnly; }
        }

        protected bool IsReadOnly
        {
            get { return _list.IsReadOnly; }
        }

        object ICollection.SyncRoot
        {
            get { return SyncRoot; }
        }

        protected object SyncRoot
        {
            get { return _list.SyncRoot; }
        }

        public IEnumerator GetEnumerator()
        {
            return _list.GetEnumerator();
        }

        public void Remove(T item)
        {
            if (item != null)
            {
                _list.Remove(item);
                OnCollectionChanged(new EventArgs());
            }
        }

        void IList.Remove(object item)
        {
            T value = item as T;
            if (value == null)
                throw GetInvalidTypeException(item);

            Remove(value);
        }

        public void RemoveAt(int index)
        {
            _list.RemoveAt(index);
            OnCollectionChanged(new EventArgs());
        }

        private static Exception GetInvalidTypeException(object obj)
        {
            return new NotSupportedException();
        }
    }
}

测试组件.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Drawing;

namespace TestCollectionEditor
{    
    public partial class TestComponent : Component
    {
        public TestComponent()
        {
            InitializeComponent();
            _position = new Point(random.Next(), random.Next());
            _size = new Size(100, 100);
            _color = Color.FromArgb(random.Next()%255,random.Next()%255,random.Next()%255);
        }

        public TestComponent(IContainer container)
        {
            container.Add(this);
            _position = new Point(random.Next(), random.Next());
            _size = new Size(10, 10);

            InitializeComponent();
        }

        private Point _position;
        private Size _size;
        private Color _color;
        private static Random random = new Random();

        public Color Color
        {
            get
            {
                return _color;
            }
        }

        public Point Position
        {
            get
            {
                return _position;
            }
        }

        public Size Size
        {
            get
            {
                return _size;
            }
        }

        public void Draw(Graphics g, Size renderFrame)
        {
            Point newPosition = new Point(Position.X % renderFrame.Width, Position.Y % renderFrame.Height);
            g.FillRectangle(new SolidBrush(Color), new Rectangle(newPosition, Size));
        }

        private void InitializeComponent()
        {
        }
    }
}

CollectionEditorTestUserControl.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace TestCollectionEditor
{
    public partial class CollectionEditorTestUserControl : UserControl
    {
        public CollectionEditorTestUserControl()
        {
            //this.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
            _collection = new TestCollectionClass(Size);
            _collection.CollectionChanged += new TestCollectionClass.CollectionChangeEventHandler(OnCollectionChanged);
            InitializeComponent();
        }

        private void OnCollectionChanged(object sender, EventArgs e)
        {
            Invalidate();
        }

        private TestCollectionClass _collection;
        public TestCollectionClass Collection
        {
            get
            {
                return _collection;
            }
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            for (int i = 0; i < _collection.Count; i++ )
            {
                TestComponent c = _collection[i];
                c.Draw(e.Graphics, Size);
            }
        }
    }
}
4

1 回答 1

0

可能是一个错误,特别是如果 Add 是动态的,而 Delete 不是。OnCollectionChanged 通知可能只是一个“添加新项目”循环,没有考虑删除。这就是添加项目起作用的原因。

在不查看实现的情况下,我希望您正在编辑的集合是控件中的集合的副本。单击确定/添加后,修改后的集合将复制回您的属性。这是删除生效的时间。

于 2009-07-22T06:31:35.600 回答