2010-04-08 4 views
8

Ho un controllo personalizzato che ha una proprietà di tipo Collection<System.Drawing.Point>. Quando utilizzo CollectionEditor per modificare questa proprietà, la finestra CollectionEditor mostra "Object does not match target type." per le proprietà "X" e "Y". Ma se io uso System.Drawing.PointF invece, non c'è fallimento.CollectionEditor che produce "L'oggetto non corrisponde al tipo di destinazione". per System.Drawing.Point

Qualcuno può spiegare perché si verifica questa differenza?

risposta

3

La differenza tra Point e PointF si trova in effetti con PointConverter. Perché questo causa un problema è una lunga storia, ma alla fine della giornata si riduce a quanto segue:

L'implementazione System.ComponentModel.ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor) in System.ComponentModel.Design.CollectionEditor .CollectionEditorCollectionForm.SelectionWrapper restituisce semplicemente this.

Secondo la pagina MSDN del suddetto metodo dell'interfaccia ICustomTypeDescriptor, un'implementazione deve

Return (s) un oggetto che contiene la proprietà descritta dal descrittore struttura specificata.

Se ho capito bene, in questo caso l'implementazione contraddice la documentazione.

Questo si basa su alcune ricerche personali, quindi non darlo per scontato. Ho pubblicato un rapporto su questo problema su Microsoft Connect, quindi speriamo di esserne sicuri in pochi giorni. Ti riporto quando viene ricevuta una risposta.

2

Non sono un esperto .NET/C#, ma il problema sembra essere da qualche parte all'interno della classe PointConverter, che viene utilizzata come TypeConverterAttribute per la classe System.Drawing.Point. L'Editor raccolta deve utilizzare qualcosa all'interno della classe PointConverter che non riesce.

Sospetto di PointConverter perché la classe PointF non ha TypeConverterAttribute e funziona correttamente.

Nel seguente esempio, che ho messo insieme usando un certo codice da MSDN, il problema è visto quando si utilizza la classe Point in una collezione, ma non con la classe MyPoint che sta usando una consuetudine 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

Grazie bde. Trovo che se faccio il TypeConverter.GetCreateInstanceSupported() restituisce true. Non funzionerà correttamente – smwikipedia

+0

GetCreateInstance() restituendo true in realtà significa che il tuo tipo è immutabile (o almeno una delle tue proprietà è di sola lettura), vale a dire che è necessario creare una nuova istanza se desideri modificare una proprietà. Sfortunatamente questo significa che non può essere sempre evitato. – kicsit

0

La mia soluzione è prima di utilizzare collectioneditor per modificare l'elenco (di punto), utilizzare TypeDescriptor.AddAttributes(GetType(Drawing.Point), New TypeConverterAttribute()) per impostare typeconverter di Point su nothing, e successivamente utilizzare TypeDescriptor.AddAttributes(GetType(Drawing.Point), New TypeConverterAttribute(GetType(PointConverter))) per impostare typeconverter su default.

Problemi correlati