CollectionEditor, выдающий «Объект не соответствует типу цели». для System.Drawing.Point - PullRequest
8 голосов
/ 08 апреля 2010

У меня есть пользовательский элемент управления со свойством типа Collection<System.Drawing.Point>. Когда я использую CollectionEditor для редактирования этого свойства, в окне CollectionEditor отображается "Object does not match target type." для свойств "X" и "Y". Но если вместо этого я использую System.Drawing.PointF, то нет ошибки.

Может кто-нибудь объяснить, почему возникает такая разница?

Ответы [ 3 ]

3 голосов
/ 19 апреля 2010

Разница между Point и PointF действительно лежит в PointConverter. Почему это вызывает проблемы - довольно длинная история, но в конце концов все сводится к следующему:

Реализация System.ComponentModel.ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor) в System.ComponentModel.Design.CollectionEditor .CollectionEditorCollectionForm.SelectionWrapper просто возвращает this.

Согласно странице MSDN вышеупомянутого метода интерфейса ICustomTypeDescriptor, реализация должна

Возвращает объект (ы), который содержит свойство, описанное указанным дескриптором свойства.

Если я правильно понимаю, в этом случае реализация противоречит документации.

Это основано на моих собственных исследованиях, поэтому не принимайте это как должное. Я разместил отчет об этой проблеме в Microsoft Connect, так что, надеюсь, мы узнаем наверняка через несколько дней. Я сообщу, когда ответ будет получен.

2 голосов
/ 17 апреля 2010

Я не эксперт по .NET / C #, но проблема, кажется, где-то внутри класса PointConverter, который используется как TypeConverterAttribute для класса System.Drawing.Point.Редактор коллекций должен использовать что-то в классе PointConverter, что не удается.

Я подозреваю, PointConverter, потому что класс PointF не имеет TypeConverterAttribute, и он отлично работает.

В следующем примере, который я собрал вместе с помощью некоторого кода из MSDN , ваша проблема видна при использовании класса Point в коллекции, но не с классом MyPoint, который использует пользовательский TypeConverter.

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

namespace WindowsControlLibrary1
{
    public class MyTypeConverter : TypeConverter
    {
        // Overrides the CanConvertFrom method of TypeConverter.
        // The ITypeDescriptorContext interface provides the context for the
        // conversion. Typically, this interface is used at design time to 
        // provide information about the design-time container.
        public override bool CanConvertFrom(ITypeDescriptorContext context,
           Type sourceType)
        {

            if (sourceType == typeof(string))
            {
                return true;
            }
            return base.CanConvertFrom(context, sourceType);
        }
        // Overrides the ConvertFrom method of TypeConverter.
        public override object ConvertFrom(ITypeDescriptorContext context,
           CultureInfo culture, object value)
        {
            if (value is string)
            {
                string[] v = ((string)value).Split(new char[] { ',' });
                return new MyPoint(int.Parse(v[0]), int.Parse(v[1]));
            }
            return base.ConvertFrom(context, culture, value);
        }
        // Overrides the ConvertTo method of TypeConverter.
        public override object ConvertTo(ITypeDescriptorContext context,
           CultureInfo culture, object value, Type destinationType)
        {
            if (destinationType == typeof(string))
            {
                return ((MyPoint)value).X + "," + ((MyPoint)value).Y;
            }
            return base.ConvertTo(context, culture, value, destinationType);
        }
    }

    [SerializableAttribute]
    [TypeConverterAttribute(typeof(MyTypeConverter))]
    public struct MyPoint
    {
        private int x;
        private int y;

        public MyPoint(int _x, int _y)
        {
            x = _x;
            y = _y;
        }

        public int X
        {
            get { return x; }
            set { x = value; }
        }
        public int Y
        {
            get { return y; }
            set { y = value; }
        }

    }

    public partial class UserControl1 : UserControl
    {
        private List<System.Drawing.Point> points;
        private List<System.Drawing.PointF> pointfs;
        private List<MyPoint> mypoints;


        public List<System.Drawing.Point> PointList
        {
            get{ return points;}
            set{ points = value;}
        }

        public List<System.Drawing.PointF> PointFList
        {
            get {return pointfs;}
            set{pointfs = value;}
        }

        public List<MyPoint> MyPointList
        {
            get { return mypoints; }
            set { mypoints = value; }
        }

        public UserControl1()
        {
            InitializeComponent();
        }
    }
}
0 голосов
/ 23 июня 2017

Мое решение до того, как вы используете collectioneditor для редактирования списка (точки), используйте TypeDescriptor.AddAttributes(GetType(Drawing.Point), New TypeConverterAttribute()), чтобы установить typeconverter of Point в ничто, и после этого используйте TypeDescriptor.AddAttributes(GetType(Drawing.Point), New TypeConverterAttribute(GetType(PointConverter))), чтобы установить typeconverter в значение по умолчанию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...