首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >托管ToolStripControlHost设计器序列化的UserControl不会发生

托管ToolStripControlHost设计器序列化的UserControl不会发生
EN

Stack Overflow用户
提问于 2009-09-02 17:19:22
回答 2查看 3.3K关注 0票数 5

我目前正在开发一个应用程序,在其中我希望在上下文菜单中显示一个UserControl。我能够(在某种程度上使用ToolStripControlHost实现这一点)。如(NumericUpDownToolStripItem代码)所示:下面是对象的代码(用VC++.net 2.0编写)。注意:在这方面有一些类似的问题,但是似乎没有人在处理序列化用户控件,只是用户控件中的标准对象。

在对象后面显示的是实际用户控件的代码,它是带有标签的用户控件和数字下拉式控件。

问题是:当我为我的应用程序加载设计器时,我可以很好地添加我的NumericUpDownToolStripItem,但是,当我打开使用公开的适当方式编辑我的用户控件时,所有这些数据都不会序列化到我的NumericUpDownToolStripItem对象的InitializeComponent方法中。其效果是在运行时加载带有所有默认值的我的控件。每次我重新加载表单时,修改都会丢失。

我试过使用定位为TypeConverter的论Msdn教程,但它没有正常工作。所有编译都很好,除了我的对象在设计网格中完全变灰了(只是访问器属性,而不是整个menupic)。我注意到的另一个问题是,这个方法不是专门为UserControls设计的,它可能有几个不同的可修改属性,而且不可能对每个属性都有重载。

所以,我有以下问题:

  1. 是我正在做的实际工作,还是我的结构方式--偏离了规范。我确信这些属性中有很多冗余。
  2. 序列化包含在另一个UserControl\toolstriphost“父”中的用户控件“子”的正确方法是什么。“子”中的任何属性都是简单值(字符串、小数等)。
  3. 当TypeConverter类没有实现时,每次我更改属性(例如标签文本)时,对象的绘画都会被劫持,行为会很奇怪,直到我重新引导了上下文\菜单或表单。是否有适当的方法通知设计师重新油漆,因为我做了一个改变?(我使用的是失效,充其量是不可靠的)。

提前谢谢。我将继续研究这个问题,并不断更新这个问题。

代码语言:javascript
复制
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
};
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-12-10 15:48:49

我最近的“工作”解决方案:

代码语言:javascript
复制
////////////////////////////////////////////////////////////////////////////////////////////////////
///   <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
EN

Stack Overflow用户

发布于 2009-09-03 20:38:19

经过仔细的研究,我找到了答案。我的方法很好,除了一个主要的问题:我根本不需要打字机。我的问题是需要一个定制的CodeDomConverter。下面是我的解决方案。

代码语言:javascript
复制
    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);
   }   
};
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1369039

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档