2010-04-08 19 views
8

Mam niestandardowy formant, który ma właściwość typu Collection<System.Drawing.Point>. Kiedy używam CollectionEditor do edycji tej właściwości, okno CollectionEditor pokazuje "Object does not match target type." dla właściwości "X" i "Y". Ale jeśli użyję zamiast tego System.Drawing.PointF, nie będzie niepowodzenia.CollectionEditor yielding "Obiekt nie pasuje do typu celu." for System.Drawing.Point

Czy ktoś może wyjaśnić, dlaczego ta różnica występuje?

Odpowiedz

3

Różnica między Point a PointF leży rzeczywiście z PointConverter. Dlaczego powoduje to problem jest dość długa historia, ale na koniec dnia sprowadza się do następujących:

Implementacja System.ComponentModel.ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor) w System.ComponentModel.Design.CollectionEditor .CollectionEditorCollectionForm.SelectionWrapper po prostu zwraca this.

Według stronie MSDN wspomnianego sposobu interfejsu ICustomTypeDescriptor, implementacja powinien

powrotu (e) przedmiot, który zawiera właściwości opisanej przez określony deskryptora właściwości.

Jeśli dobrze rozumiem, w tym przypadku realizacja jest sprzeczna z dokumentacją.

Jest to oparte na moich własnych badaniach, więc nie traktuj tego jako oczywiste. Wysłałem raport o tym problemie na Microsoft Connect, więc mam nadzieję, że dowiemy się na pewno za kilka dni. Powiadomię cię, gdy otrzymam odpowiedź.

2

Nie jestem ekspertem .NET/C#, ale problem wydaje się być gdzieś w klasie PointConverter, która jest używana jako TypeConverterAttribute dla klasy System.Drawing.Point. Edytor kolekcji musi używać czegoś z klasy PointConverter, która kończy się niepowodzeniem.

Podejrzewam, że PointConverter, ponieważ klasa PointF nie ma TypeConverterAttribute i działa poprawnie.

W poniższym przykładzie, który ja brukowanych razem przy użyciu kodu z MSDN, Twój problem jest widoczne podczas korzystania z klasy Point w kolekcji, ale nie z klasą MyPoint który używa niestandardowych 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

Dzięki bde. Uważam, że jeśli sprawię, że TypeConverter.GetCreateInstanceSupported() zwróci true. To nie będzie działało dobrze – smwikipedia

+0

Metoda zwracania true przez GetCreateInstance() faktycznie oznacza, że ​​twój typ jest niezmienny (lub przynajmniej jedna z właściwości jest tylko do odczytu), to znaczy, że nowa instancja musi zostać utworzona, jeśli chcesz zmodyfikować właściwość. Niestety oznacza to, że nie zawsze można tego uniknąć. – kicsit

0

Moje rozwiązanie jest przed użyciem collecteditor do edycji listy (punktu), użyj TypeDescriptor.AddAttributes(GetType(Drawing.Point), New TypeConverterAttribute()), aby ustawić typeconverter z Point to nothing, a następnie użyj TypeDescriptor.AddAttributes(GetType(Drawing.Point), New TypeConverterAttribute(GetType(PointConverter))), aby ustawić typeconverter jako domyślny.

Powiązane problemy