C# ToolStripControlHost托管用户控件设计器序列化WIN';不会发生
我目前正在开发一个应用程序,希望在上下文菜单中显示UserControl。我能够(使用ToolStripControlHost在某种程度上实现这一点)。如(NumericUpDownToolStripItem代码)所示:下面是对象的代码(用VC++.net 2.0编写)。注意:在这方面有一些半相似的问题,但似乎没有一个是关于序列化usercontrols的,只是usercontrols中的标准对象 对象后面显示的是实际usercontrol的代码,它是一个带标签的usercontrol和一个numericupdown控件 问题是:当我为我的应用程序加载设计器时,我可以添加NumericUpDownToolStripItem,但是,当我打开use The exposed Property来编辑我的usercontrol时,没有一个数据被序列化到NumericUpDownToolStripItem对象的InitializeComponent方法中。其效果是我的控件在运行时加载所有默认值。每次我重新加载表单时,修改都会丢失 我曾尝试使用找到的TypeConverter教程,但没有正常工作。一切都编译得很好,除了我的对象在设计网格中完全变灰(只是accessor属性,而不是整个menupic)。我注意到的另一个问题是,这个方法不是专门为UserControls设计的,UserControls可能有几个不同的可修改属性,并且不可能每个属性都有重载 因此,我有以下问题:C# ToolStripControlHost托管用户控件设计器序列化WIN';不会发生,c#,.net,visual-studio,winforms,serialization,C#,.net,Visual Studio,Winforms,Serialization,我目前正在开发一个应用程序,希望在上下文菜单中显示UserControl。我能够(使用ToolStripControlHost在某种程度上实现这一点)。如(NumericUpDownToolStripItem代码)所示:下面是对象的代码(用VC++.net 2.0编写)。注意:在这方面有一些半相似的问题,但似乎没有一个是关于序列化usercontrols的,只是usercontrols中的标准对象 对象后面显示的是实际usercontrol的代码,它是一个带标签的usercontrol和一个nu
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
};
好吧,经过多次搜索,我找到了答案。我的方法很好,除了一个主要问题:我根本不需要类型转换器。我的问题是需要一个定制的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);
}
};
通用
ref类CustomCodeDomSerializer:CodeDomSerializer
{
public:virtual Object^反序列化(IDesignerSerializationManager^管理器,Object^ codeObject)重写
{
//这就是我们将组件与序列化程序关联的方式。
CodeDomainSerializer^baseClassSerializer=(CodeDomainSerializer^)管理器->
GetSerializer(T::typeid->BaseType,CodeDomSerializer::typeid);
//这是最简单的情况,在这种情况下,类只调用基类
//做这项工作。
返回baseClassSerializer->反序列化(管理器,codeObject);
}
公共:虚拟对象^Serialize(IDesignerSerializationManager^manager,对象^value)重写
{
//以与相同的方式将组件与序列化程序关联
//反序列化
CodeDomainSerializer^baseClassSerializer=(CodeDomainSerializer^)管理器->
GetSerializer(T::typeid->BaseType,CodeDomSerializer::typeid);
对象^codeObject=baseClassSerializer->Serialize(管理器,值);
//codeObject中可能有任何内容。此示例在
//CodeStatementCollection。
if(动态_转换(codeObject))
{
CodeStatementCollection^语句=(CodeStatementCollection^)codeObject;
//代码语句集合有效,请添加注释。
String^commentText=“此注释是由自定义序列化程序添加到此对象的。”;
CodeCommentStatement^comment=gcnew CodeCommentStatement(commentText);
语句->插入(0,注释);
}
返回代码对象;
}
};
////////////////////////////////////////////////////////////////////////////////////////////////////
///
///此Usercontrol是一个简单的标签,与数字UpDown相结合。下面的班级
///它会将此项包装在toolstrip容器中,以便它可以成为上下文菜单的一部分
///
////////////////////////////////////////////////////////////////////////////////////////////////////
[DesignerSerializer(CustomCodeDomainSerializer::typeid,CodeDomainSerializer::typeid)]
公共引用类LabeledNumericUpDown:UserControl
{
public:事件事件处理程序^NumericUpDownValueChanged;
公共:[类别(“自定义信息”)、说明(L“要显示的文本”),
DefaultValue(L“默认文本”)、可浏览(true)、可本地化(true)、NotifyParentProperty(true)]
属性字符串^DisplayText
{
字符串^get()
{
返回此->标签->文本;
}
无效集(字符串^val)
{
此->标签->文本=val;
如果(此->设计模式| |
LicenseManager::UsageMode==LicenseSusageMode::Designtime)
此->无效();
}
}
//设计师的东西不重要
}
[ToolStripItemDesignerAvailability(ToolStripItemDesignerAvailability::All),
ToolboxBitmap(::NumericUpDown::typeid)]
公共引用类NumericUpDownToolStripItem:ToolStripControlHost
{
//替换此类型
私有:LabeledNumericUpDown^控制;
public:[类别(“对象主机”),描述(L“托管用户控制对象”),
DisplayName(“UserControl对象”)、可浏览(true)、NotifyParentProperty(true),
DesignerSerializationVisibility(DesignerSerializationVisibility::Content)]
//替换这个p
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <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);
}
};