【问题标题】:CollectionEditor yielding "Object does not match target type." for System.Drawing.PointCollectionEditor 产生“对象与目标类型不匹配。”对于 System.Drawing.Point
【发布时间】:2011-02-05 13:34:27
【问题描述】:

我有一个自定义控件,它的属性类型为Collection<System.Drawing.Point>。当我使用CollectionEditor 编辑此属性时,CollectionEditor 窗口显示"Object does not match target type.""X""Y" 属性。但是如果我改用System.Drawing.PointF,就不会失败。

谁能解释一下为什么会出现这种差异?

【问题讨论】:

    标签: c# collectioneditor


    【解决方案1】:

    Point 和 PointF 的区别确实在于 PointConverter。为什么这会导致问题是一个很长的故事,但归根结底,它归结为以下几点:

    System.ComponentModel.Design.CollectionEditor .CollectionEditorCollectionForm.SelectionWrapper 中的 System.ComponentModel.ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor) 实现仅返回 this

    根据上述ICustomTypeDescriptor接口方法的MSDN页面,应该有一个实现

    返回一个对象,该对象包含指定属性描述符所描述的属性。

    如果我理解正确,在这种情况下,实现与文档相矛盾。

    这是基于我自己的一些研究,所以不要想当然。我在 Microsoft Connect 上发布了有关此问题的报告,因此希望我们能在几天内确定。收到答复后我会报告。

    【讨论】:

      【解决方案2】:

      我不是 .NET / C# 专家,但问题似乎出在 PointConverter 类中,该类用作 System.Drawing.Point 类的 TypeConverterAttribute。集合编辑器必须在失败的 PointConverter 类中使用某些东西。

      我怀疑PointConverter,因为PointF 类没有TypeConverterAttribute,它工作正常。

      在以下示例中,我使用 MSDN 中的一些代码拼凑而成,在集合中使用 Point 类时会出现问题,但使用自定义 @987654331 的 MyPoint 类不会出现问题@。

      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();
              }
          }
      }
      

      【讨论】:

      • 谢谢bde。我发现如果我让 TypeConverter.GetCreateInstanceSupported() 返回 true。它不会很好地发挥作用
      • GetCreateInstance() 返回 true 实际上意味着你的类型是不可变的(或者至少你的一个属性是只读的),也就是说,如果你想修改一个新的实例,就需要创建一个新的实例。财产。不幸的是,这意味着它不能总是避免。
      【解决方案3】:

      我的解决方案是在使用collectioneditor编辑列表(点)之前,使用TypeDescriptor.AddAttributes(GetType(Drawing.Point), New TypeConverterAttribute())将Point的typeconverter设置为空,然后使用TypeDescriptor.AddAttributes(GetType(Drawing.Point), New TypeConverterAttribute(GetType(PointConverter)))将typeconverter设置为默认值。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-01-02
        • 2017-02-04
        • 1970-01-01
        相关资源
        最近更新 更多