我有一个具有 type 属性的自定义控件Collection<System.Drawing.Point>
。当我CollectionEditor
用来编辑此属性时,CollectionEditor
窗口会显示"Object does not match target type."
和"X"
属性"Y"
。但如果我System.Drawing.PointF
改用,就没有失败。
谁能解释为什么会出现这种差异?
我有一个具有 type 属性的自定义控件Collection<System.Drawing.Point>
。当我CollectionEditor
用来编辑此属性时,CollectionEditor
窗口会显示"Object does not match target type."
和"X"
属性"Y"
。但如果我System.Drawing.PointF
改用,就没有失败。
谁能解释为什么会出现这种差异?
Point 和 PointF 的区别确实在于 PointConverter。为什么这会导致问题是一个很长的故事,但归根结底,它归结为以下几点:
中的System.ComponentModel.ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor)
实现System.ComponentModel.Design.CollectionEditor
.CollectionEditorCollectionForm.SelectionWrapper
简单地返回this
。
根据上述ICustomTypeDescriptor
接口方法的MSDN页面,实现应该
返回包含由指定属性描述符描述的属性的对象。
如果我理解正确,在这种情况下,实现与文档相矛盾。
这是基于我自己的一些研究,所以不要认为这是理所当然的。我在 Microsoft Connect 上发布了有关此问题的报告,因此希望我们能在几天内确定。收到答复后我会报告。
我不是 .NET / C# 专家,但问题似乎在类中的某个地方,PointConverter
它被用作TypeConverterAttribute
System.Drawing.Point
。集合编辑器必须在PointConverter
失败的类中使用某些东西。
我怀疑PointConverter
是因为PointF
班级没有TypeConverterAttribute
,而且效果很好。
在下面的示例中,我使用MSDN中的一些代码拼凑在一起,在集合中使用类时会看到您的问题Point
,但在MyPoint
使用 custom 的类中不会出现问题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();
}
}
}
我的解决方案是在您使用 collectioneditor 编辑列表(点)之前,使用 TypeDescriptor.AddAttributes(GetType(Drawing.Point), New TypeConverterAttribute())
将 Point 的 typeconverter 设置为空,然后TypeDescriptor.AddAttributes(GetType(Drawing.Point), New TypeConverterAttribute(GetType(PointConverter)))
将 typeconverter 设置为默认值。