gpt4 book ai didi

c# - 托管 UserControl 设计器的 ToolStripControlHost 不会发生序列化

转载 作者:太空狗 更新时间:2023-10-29 23:42:40 25 4
gpt4 key购买 nike

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

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

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

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

那么,我有以下问题:

  1. 我正在做的事情是否实用,或者我的结构是否偏离规范。我敢肯定属性中有很多冗余。
  2. 序列化包含在另一个 UserControl\toolstriphost“父”中的用户控件“子”的正确方法是什么。 “child”中的任何属性都是简单值(字符串、小数等)。
  3. 当未实现 TypeConverter 类时,每次我更改一个属性(例如标签文本)时,对象的绘制都会被顶起并表现得很奇怪,直到我重新引导上下文\菜单或表单。有没有合适的方式通知设计师因为我做了改动而重新粉刷? (我使用了 invalidate,它充其量是狡猾的)。

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

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

关于c# - 托管 UserControl 设计器的 ToolStripControlHost 不会发生序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1369039/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com