2009-09-02 16 views
5

現在、コンテキストメニュー内にUserControlを表示するアプリケーションを開発中です。私は(これはToolStripControlHostを使用していくらか達成できました)。以下に示す(NumericUpDownToolStripItem code):以下はオブジェクトのコードです(VC++ .net 2.0で書かれています)。注:これに半類似のSOの質問がありますが、usercontrolsの標準オブジェクトだけをシリアル化するユーザーコントロールを扱うものはありません。UserControlデザイナーをホストするToolStripControlHostシリアライズは発生しません。

オブジェクトの後には、実際のusercontrol(ラベルを持つusercontrol)とnumericupdownコントロールのコードが表示されます。

問題:私のアプリケーションのデザイナを読み込むときにNumericUpDownToolStripItemをうまく追加することができますが、公開したプロパティを開いて私のusercontrolを編集すると、そのデータはInitializeComponentメソッドにはシリアル化されません私のNumericUpDownToolStripItemオブジェクトの。この効果は、実行時にすべてのデフォルトでのコントロールのロードになります。私のフォームをリロードするたびに、変更は失われます。

On MsdnにあるTypeConverterチュートリアルを試しましたが、正しく動作しませんでした。私のオブジェクトがデザイングリッド内で完全にグレーアウトされていることを除いて、すべてのものがうまくコンパイルされました(メーピーピング全体ではなくアクセサープロパティのみ)。私が気付いたもう一つの問題は、このメソッドはUserControlsのために特別に設計されていないということです.UserControlsにはいくつかの異なる変更可能なプロパティがあり、それぞれに対してオーバーロードを持つことはできません。

だから、私は次の質問を持っている:

  1. は私が実用的にやっているか、それとも私の構造の道オフが規範です。私はその属性に多くの冗長性があると確信しています。
  2. 別のUserControl \ toolstriphost 'parent'に含まれるusercontrol 'child'をシリアル化する正しい方法は何ですか。 '子'のプロパティはすべて単純値(文字列、小数点など)です。
  3. TypeConverterクラスが実装されていないときに、プロパティ(ラベルのテキストなど)を変更するたびに、オブジェクトのペイントがすべて終了し、コンテキスト\メニューまたはフォームを取り除くまで、奇妙な動作をします。私が変更を加えたので、デザイナーに再塗装を知らせる適切な方法はありますか? (私は無効にしていました。

ありがとうございます。私はこれを研究し続け、質問を更新し続けるつもりです。

NumericUpDownToolStripItem Class: 
    [ToolStripItemDesignerAvailability(ToolStripItemDesignerAvailability::All)] 
    public ref class NumericUpDownToolStripItem : public ToolStripControlHost 
    { 
     public: 
     [DesignerSerializationVisibility(DesignerSerializationVisibility::Content | 
      DesignerSerializationVisibility::Visible)] 
     property LabeledNumericUpDown ^LabeledNumericUpDownControl 
     { 
     LabeledNumericUpDown ^get() { return (LabeledNumericUpDown^)this->Control; } 
     } 

     public: NumericUpDownToolStripItem(void) : 
      ToolStripControlHost(gcnew LabeledNumericUpDown()) {} 

     protected: void OnSubscribeControlEvents(Control ^control) new { //irrelevant to question } 
     protected: void OnUnsubscribeControlEvents(Control ^control) new { //irrelevant to question }  
    }; 

public ref class LabeledNumericUpDown : public UserControl 
{ 
    public: [ DesignerSerializationVisibility(DesignerSerializationVisibility::Content | 
    DesignerSerializationVisibility::Visible)] 
    property String ^DisplayText { 
     String ^get() { 
     return this->label->Text; 
     } 
     void set(String ^val) { 
     if(this->label->Text != val) 
     { 
      this->label->Text = val; 
      this->Invalidate(); 
     } 
     } 
    } 

//constructor 
//destructor 
//initiailecomponent 
}; 
+0

が、これは、私はこの正確な問題に対処見つけることができる唯一のポストのようです。私はあなたのコントロールのホストデザイナーを見えるようにするためにあなたが何をしたのか疑問に思っています。私が何をしても、ビジュアルスタジオに表示させることはできません。私はMSDNの主張がデザイナーのサポートを可能にするために必要なものすべてを適用しました。いくつかの指針は非常に高く評価されます。 –

+0

私は何をしたのか正確には覚えていませんが、このコントロールがリリースされ、「製品」になっていることはわかっています。私は、コードを追跡し、コントロール自体に何か違いがあるかどうかを再確認しようとします。 – greggorob64

+1

私の新しい投稿を確認する、私は現在の作業設定を再投稿 – greggorob64

答えて

1

私の最も最近、「作業」解決策:スレッドの復活のために申し訳ありません

//////////////////////////////////////////////////////////////////////////////////////////////////// 
/// <summary> 
/// This Usercontrol is a simple label coupled with a numericupdown. The class following 
/// it will wrap this item in toolstrip container so that it can be part of a contextmenu 
/// </summary> 
//////////////////////////////////////////////////////////////////////////////////////////////////// 
[DesignerSerializer(CustomCodeDomSerializer<LabeledNumericUpDown^>::typeid, CodeDomSerializer::typeid)] 
public ref class LabeledNumericUpDown : UserControl 
{ 
    public: event EventHandler ^NumericUpDownValueChanged; 

    public: [Category("Custom Information"), Description(L"Text to display"), 
      DefaultValue(L"Default Text"), Browsable(true), Localizable(true), NotifyParentProperty(true)] 
    property String ^DisplayText 
    { 
     String ^get(); 
     void set(String ^val); 
    } 

    public: [Category("Custom Information"), Description(L"NumericUpDown Value"), 
      DefaultValue(1), Browsable(true), Localizable(true), NotifyParentProperty(true)] 
    property Decimal UpDownValue 
    { 
     Decimal get(); 
     void set(Decimal val); 
    } 

    public: [Category("Custom Information"), Description(L"NumericUpDown Maximum"), 
      DefaultValue(100), Browsable(true), Localizable(true), NotifyParentProperty(true)] 
    property Decimal UpDownMaximum 
    { 
     Decimal get(); 
     void set(Decimal val); 
    } 

    public: [Category("Custom Information"), Description(L"NumericUpDown Minimum"), 
      DefaultValue(0), Browsable(true), Localizable(true), NotifyParentProperty(true)] 
    property Decimal UpDownMinimum 
    { 
     Decimal get(); 
     void set(Decimal val); 
    } 

    private: bool SupressEvents; 
    public: Void UpDownValueSet_NoEvent(int Val); 
    private: Void numericUpDown_ValueChanged(Object ^sender, EventArgs ^e); 
    public: LabeledNumericUpDown(void); 
    private: System::Windows::Forms::NumericUpDown^ numericUpDown; 
    private: System::Windows::Forms::Label^ label; 
    private: System::Windows::Forms::TableLayoutPanel^ tableLayoutPanel1; 
    private: System::ComponentModel::Container ^components; 
    #pragma region Windows Form Designer generated code 
    void InitializeComponent(void); 
}; 

//////////////////////////////////////////////////////////////////////////////////////////////////// 
/// <summary> CustomCodeDomSerializer 
/// This is a specialized usercontrol designed to incapsulate another usercontrol (in this case a 
/// NumericUpDownToolStripItem. In order to use this class, you must copy this entire class and 
/// create a new object. (You can do this right underneath your usercontrol in the same file 
/// if you wish. You must specifiy the type of your object every place its mentioned. 
/// 
/// To Note: The toolbox bitmap is what the icon will look like. You can specify any old control. 
/// It is possible to use a custom icon, but I can't figure out how. 
///</summary> 
/// 
/// <value> The tool strip control host. </value> 
//////////////////////////////////////////////////////////////////////////////////////////////////// 

[ToolStripItemDesignerAvailability(ToolStripItemDesignerAvailability::All), 
ToolboxBitmap(::NumericUpDown::typeid)] 
public ref class NumericUpDownToolStripItem : ToolStripControlHost 
{ 
    //replace this type 
    private: LabeledNumericUpDown ^_Control; 

    public: [Category("Object Host"), Description(L"Hosted usercontrol object"), 
    DisplayName("UserControl Object"), Browsable(true), NotifyParentProperty(true), 
    DesignerSerializationVisibility(DesignerSerializationVisibility::Content)] 
    //replace this properties type 
    property LabeledNumericUpDown ^UserControlObject 
    { 
    //replace this properties return type 
    LabeledNumericUpDown ^get() { return this->_Control; } 
    } 

    public: NumericUpDownToolStripItem(void) : 
     System::Windows::Forms::ToolStripControlHost(gcnew FlowLayoutPanel()) 
    { 
     //replace this constructor type 
     _Control = gcnew LabeledNumericUpDown(); 

     //don't touch this 
     FlowLayoutPanel ^thePanel = (FlowLayoutPanel ^)this->Control; 
     thePanel->BackColor = Color::Transparent; 
     thePanel->Controls->Add(_Control); 
    } 
}; 
1

多くの検索の後、私は答えを見つけました。 1つの大きな問題を除いて、私の方法論はうまくいきました。私は型変換器を一切必要としませんでした。私の問題は、カスタムCodeDomConverterの必要性でした。私の解決策は以下のとおりです。

generic<typename T> 
    ref class CustomCodeDomSerializer : CodeDomSerializer 
    { 
    public: virtual Object ^Deserialize(IDesignerSerializationManager ^manager, Object ^codeObject) override 
     { 
      // This is how we associate the component with the serializer. 
      CodeDomSerializer ^baseClassSerializer = (CodeDomSerializer^)manager-> 
      GetSerializer(T::typeid->BaseType, CodeDomSerializer::typeid); 

      //This is the simplest case, in which the class just calls the base class 
      // to do the work. 
      return baseClassSerializer->Deserialize(manager, codeObject); 
     } 

     public: virtual Object ^Serialize(IDesignerSerializationManager ^manager, Object ^value) override 
     { 
      //Associate the component with the serializer in the same manner as with 
      // Deserialize 
      CodeDomSerializer ^baseClassSerializer = (CodeDomSerializer^)manager-> 
      GetSerializer(T::typeid->BaseType, CodeDomSerializer::typeid); 

      Object ^codeObject = baseClassSerializer->Serialize(manager, value); 

      //Anything could be in the codeObject. This sample operates on a 
      // CodeStatementCollection. 
      if (dynamic_cast<CodeStatementCollection^>(codeObject)) 
      { 
      CodeStatementCollection ^statements = (CodeStatementCollection^)codeObject; 

      // The code statement collection is valid, so add a comment. 
      String ^commentText = "This comment was added to this Object by a custom serializer."; 
      CodeCommentStatement ^comment = gcnew CodeCommentStatement(commentText); 
      statements->Insert(0, comment); 
      } 
      return codeObject; 
     } 

}; 




//////////////////////////////////////////////////////////////////////////////////////////////////// 
/// <summary> 
/// This Usercontrol is a simple label coupled with a numericupdown. The class following 
/// it will wrap this item in toolstrip container so that it can be part of a contextmenu 
/// </summary> 
//////////////////////////////////////////////////////////////////////////////////////////////////// 
[DesignerSerializer(CustomCodeDomSerializer<LabeledNumericUpDown^>::typeid, CodeDomSerializer::typeid)] 
public ref class LabeledNumericUpDown : UserControl 
{ 
    public: event EventHandler ^NumericUpDownValueChanged; 

    public: [Category("Custom Information"), Description(L"Text to display"), 
      DefaultValue(L"Default Text"), Browsable(true), Localizable(true), NotifyParentProperty(true)] 
    property String ^DisplayText 
    { 
     String ^get() 
     { 
     return this->label->Text; 
     } 
     void set(String ^val) 
     { 
     this->label->Text = val; 
     if(this->DesignMode || 
      LicenseManager::UsageMode == LicenseUsageMode::Designtime) 
      this->Invalidate(); 

     } 
    } 
    //designer stuff not important 
} 




[ToolStripItemDesignerAvailability(ToolStripItemDesignerAvailability::All), 
ToolboxBitmap(::NumericUpDown::typeid)] 
public ref class NumericUpDownToolStripItem : ToolStripControlHost 
{ 
    //replace this type 
    private: LabeledNumericUpDown ^_Control; 

    public: [Category("Object Host"), Description(L"Hosted usercontrol object"), 
    DisplayName("UserControl Object"), Browsable(true), NotifyParentProperty(true), 
    DesignerSerializationVisibility(DesignerSerializationVisibility::Content)] 
    //replace this properties type 
    property LabeledNumericUpDown ^UserControlObject 
    { 
    //replace this properties return type 
    LabeledNumericUpDown ^get() { return this->_Control; } 
    } 

    public: NumericUpDownToolStripItem(void) : 
     System::Windows::Forms::ToolStripControlHost(gcnew FlowLayoutPanel()) 
    { 
     //replace this constructor type 
     _Control = gcnew LabeledNumericUpDown(); 

     //don't touch this 
     FlowLayoutPanel ^thePanel = (FlowLayoutPanel ^)this->Control; 
     thePanel->BackColor = Color::Transparent; 
     thePanel->Controls->Add(_Control); 
    } 
}; 
関連する問題