- PR -

コンポーネントのプロパティの永続化指定での問題

1
投稿者投稿内容
はなたれ小僧
常連さん
会議室デビュー日: 2003/07/17
投稿数: 21
投稿日時: 2005-01-04 10:26
少し前にコンポーネントクラスの複合型プロパティの作り方について教えていただき何とか形になってきたところですが、解決できない点があってお尋ねする次第です。

簡単な例で、.NETでサポートされた(X,Y)のフィールドを持つPoint型(int)、PointF型(float)というのがありますが、PointD型(double)やPointB型(bool)というのがないので自作しています。このとき、

Point,PointFはクラスではなく構造体(struct)だと説明されているので、PointD,PointBも構造体にしてみたのですが、そのプロパティが永続化されるように宣言して作ったコンポーネントクラスをフォームに配置してやるとフォームのコンストラクタが実行するInitializeComponent()メソッドの中に記述される永続化のコードがコンパイルでエラーになります。

CS1612.CS: C:\Projects\MyApp\Form1.cs(190): 変数ではないため、'MyLib.MyClass.Point' の戻り値を変更できません。

プロパティがPoint型の場合には
-- this.myCompo.Point = new System.Drawing.Point(10,10);
のようにnew演算子を伴って記述され何の問題もありませんが、自作のPointD型だと
-- this.myCompo.Point.X = 10;
-- this.myCompo.Point.Y = 10;
のように個別に値が代入される形式になってしまうのが原因です。

このエラーが次のように書きなさいと言っていることはわかるのですが、なにせデザイナによる自動記述の部分なので手が出ません。
-- PointD myPoint = this.myCompo.Point;
-- myPoint.X = 10;
-- myPoint.Y = 10;
-- this.myCompo.Point = myPoint;

そこで、PointDをクラスに変更してやると上のような違いがあってもエラー扱いされなくなるために一応ゴールできます。

しかし、標準のPointは構造体で自作のPointDはクラスだというのもどうにも気に入りません。
ここでは単純な例で示しましたが、他のすべてのカスタムプロパティについても永続化コードをnewで設定してもらえないという点で同じです。newで記述してもらうには何かの属性が必要な気がするのですが、見当がつきません。何か知恵を貸していただけませんでしょうか。

プロパティのクラスは次のよなものでTypeConverterも付加して使っています。クラスに変更するときは単にstructをclassにするだけです。

コード:
[Serializable()]
public struct PointD
{
    private double x;
    private double y;
    public PointD(double x, double y) {this.x = x; this.y = y;}
    public double X { get {return this.x;} set {this.x = value;} }
    public double Y { get {return this.y;} set {this.y = value;} }
    public override string ToString() {....}
    public override bool Equals(Object obj) {....}
    public override int GetHashCode() {....}
}
//コンポーネントのクラス
public class MyCompoClass : System.Windows.Forms.PictureBox
{
    //(コンストラクタなど省略)

    private PointD point;

    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public PointD Point { get {return this.point;} set {this.point = value;} }
}



Win2000//VS.NET2003/Enterprise//C#//Windowsアプリの環境です。よろしくお願いします。
はなたれ小僧
常連さん
会議室デビュー日: 2003/07/17
投稿数: 21
投稿日時: 2005-01-04 20:18
調査の途中経過です。

Visual Designers におけるコード生成のカスタマイズ
http://www.microsoft.com/japan/msdn/net/general/custcodegen.asp#custcodegen_topic8

MSDNの上の解説が答えを示しているのではないかと考え、"カスタム型に対するコード生成"の段落にあるPoint型の場合のTypeConverterの記述を参考にこれまでの内容にCanConvertTo()とConvertTo()の2つのメソッドを加えてテストしているのですが、次のような状況でした。
・CanConvertTo()がtrueを返すと永続化コードがまったく挿入されなくなる。
・CanConvertTo()がfalseを返すようにするとこれまでどおりに2行のコードを生成する。
・プロパティ記述時にConvertTo()メソッドがInstanceDescriptorにより値を返す行にはちゃんと入ってくる。

まったく筋違いなのか、もうちょっとのところにいるのか、図りかねています。
プログラムの本文ではなくこのようなデザイナに対するコードの場合、何が悪くて動かないのかデバッグするのも容易ではなく困っていますが、どのようにされていますでしょうか。

型コンバータの記述は次のようなものです。

コード:
[Serializable(), 
TypeConverter(typeof(PointDConverter))] 
public struct PointD {....} //省略

internal class PointDConverter : ExpandableObjectConverter 
{
  public override bool CanConvertFrom() {....} //省略
  public override object ConvertFrom() {....} //省略

  public override bool CanConvertTo(ITypeDescriptorContext context, 
    Type destinationType) 
  {
    if (destinationType == typeof(InstanceDescriptor)) 
      return true;
    return base.CanConvertTo(context, destinationType);
  }
  public override object ConvertTo(ITypeDescriptorContext context, 
    CultureInfo culture, object value, Type destinationType) 
  {  
    if (destinationType == typeof(InstanceDescriptor) && value is PointD) 
    {
      PointD pt = (PointD)value;
      ConstructorInfo ctor = typeof(PointD).GetConstructor(
        new Type[] {typeof(double), typeof(double)});
      if (ctor != null) 
      {
        return new InstanceDescriptor(ctor, new object[] {pt.X, pt.Y}, true);
      }
    }
    return base.ConvertTo(context, culture, value, destinationType);
  }
}


はなたれ小僧
常連さん
会議室デビュー日: 2003/07/17
投稿数: 21
投稿日時: 2005-01-07 15:12
自己レスです。簡単なことでしたが、解決しましたので報告だけします。

型コンバータにCanConvertToとConvertToを追加した上でプロパティの属性指定の
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]

[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
にすればよかっただけのことでした。

とんでもない道草を食らってしまいましたが、型コンバータの勉強になりました。
1

スキルアップ/キャリアアップ(JOB@IT)