2009-09-02 12 views
5

Şu anda, bir bağlam menüsünde UserControl görüntülemek istediğim bir uygulama geliştiriyorum. Ben (biraz ToolStripControlHost kullanarak bunu başardı) başardı. (NumericUpDownToolStripItem kodu) içinde gösterilmiştir: aşağıdaki nesnenin kodudur (VC++. Net 2.0 ile yazılmıştır). Not: Bu konuda yarı benzer SO soruları vardır, ancak hiçbirisi usercontrols serisinde sadece standart nesne serileştiren usercontrols ile ilgilenmiyor.ToolStripControlHost bir UserControl tasarımcısı barındırma Serileştirme gerçekleşmeyecek

Nesneyi izleyen, bir usercontrol olan bir gerçek usercontrol kodudur ve bir numericupdown denetimi.

Sorun: Tasarımcımı uygulamam için yüklediğimde, NumericUpDownToolStripItem öğemi ekleyebilirim, ancak, usercontrolımı düzenlemek için açığa çıkarılmış mülkün kullanımını açtığımda, bu verilerin hiçbiri InitializeComponent yöntemine serileştirilmiyor benim NumericUpDownToolStripItem nesnesinin. Bunun etkisi, çalışma zamanında tüm varsayılan değerler ile kontrol yüklerim. Ve formumu yeniden yüklediğimde, değişiklikler kayboluyor.

On Msdn'da bulunan TypeConverter eğitimini kullanmayı denedim, ancak düzgün çalışmadı. Her şey gayet iyi derlenmişti, nesnem tamamen tasarım kılavuzunda tamamen grileşti (sadece menşeli değil, sadece erişimci mülkiyeti). Fark ettiğim bir başka sorun da, bu yöntemin, farklı modifiye edilebilir özelliklere sahip olabilecek ve muhtemelen her biri için bir aşırı yüklenmeye sahip olmayan UserControls için tasarlanmamış olmasıdır.

Yani, şu soru var:

  1. Ben pratik yapıyorum, yoksa benim yapısı yolu kapalı normlar olduğunu. Eminim özniteliklerde fazlalık var.
  2. Başka bir UserControl \ toolstriphost 'ebeveyni' içinde bulunan bir usercontrol 'child' serileştirmek için doğru yöntem nedir. 'Çocuk' daki herhangi bir özellik basit değerlerdir (Strings, Decimals, vb.).
  3. TypeConverter sınıfı uygulanmadığında, bir özelliği her değiştirdiğimde (örneğin bir etiket metni), bağlamın menüsünü veya formunu serbest bırakıncaya kadar, nesnenin resmi tümüyle kilitlenir ve garip davranır. Tasarımcıyı tekrar boyamak için uygun bir yol var mı, çünkü değişiklik yaptım mı? (En iyi tehlikeli olan geçerliliği kullanmıştım).

Şimdiden teşekkürler. Bunu araştırmaya ve soruyu güncel tutmaya devam edeceğim.

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

iplik diriliş için üzgünüm, ama bu tam olarak bu konu ile ilgili bulabilirsiniz sadece post gibi görünüyor. Denetleyici ana bilgisayar tasarımcısını görünür kılmak için ne yaptığınızı merak ediyorum - Ne yaptığımın bir önemi yok, ben görsel stüdyonun göstermesini sağlayamıyorum. MSDN iddialarının tasarımcı desteğini etkinleştirmesi gerektiği her şeyi uyguladım ve hiçbir şey. Bazı işaretçiler çok takdir edilecektir. –

+0

Tam olarak ne yaptığımı hatırlamıyorum, ama bu kontrolün piyasaya sürüldüğünü ve "üründe" olduğunu biliyorum. Kodu takip etmeye çalışacağım ve herhangi bir fark olup olmadığını görmek için kontrolün kendisini yeniden yayınlayacağım. – greggorob64

+1

Yeni gönderiyi kontrol edin, şu anki çalışma kurulumumu yeniden yayınladım – greggorob64

cevap

1

Benim en son, "çalışma" çözüm:

//////////////////////////////////////////////////////////////////////////////////////////////////// 
/// <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

Pek çok aramadan sonra cevabımı buldum. Metodum, sadece bir problem için çok iyiydi: Hiç türden dönüştürücülere gerek yoktu. Benim sorunum özel bir CodeDomConverter için ihtiyaç oldu. Aşağıda gösterilen çözüm benim çözümüm.

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); 
    } 
};