【发布时间】:2016-12-01 22:45:01
【问题描述】:
我编写了自己的 UITypeEditor,并在 @Sefe 和 THIS 链接的帮助下实现了我的目标。
在此设置中,BaseForm 扩展了 System.Windows.Forms.Form。在这里,我将我的属性 (List<Control> ActionButtons) 放入了具有自定义 UITypeEditor 的属性,例如模态样式。
恢复的工作流程(这里的所有内容都在设计时):
1 - 打开我的表单。
2 - 单击 MyForm 属性面板上的 ActionButtons(由 BaseForm 继承)省略号 [...]。
3 - 打开一个自定义表单,其中包含我想要选择的充气对象。 (此表单由我的 CustomUITypeEditor 调用)
4 - 选择我想要的对象,然后关闭表单。所以现在,MyForm 中的数据正常,并序列化到 Designer.cs 文件中。我可以在省略号中再次单击重新打开该 EditorUI,然后查看我之前选择的对象。
5 - 现在当我关闭 MyForm 并重新打开它时,所有数据都丢失了!!!但数据仍然序列化到 Designer.cs 中。
6 - 如果我使用 string 而不是 List<Control> 执行所有这些步骤,则一切正常。
下面是我的代码:
public class CollectionTypeEditor : UITypeEditor {
private IWindowsFormsEditorService _editorService = null;
private ICollection<Control> mControls = null;
private List<Control> mPickedControls = null;
// Editor like Modal style
public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) {
return UITypeEditorEditStyle.Modal;
}
// Opens modal and get returned data
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value) {
if (provider == null)
return value;
_editorService = (IWindowsFormsEditorService) provider
.GetService(typeof(IWindowsFormsEditorService));
if (_editorService == null)
return value;
mControls = new List<Control>();
// retrieve old data
mPickedControls = value as List<Control>;
if (mPickedControls == null)
mPickedControls = new List<Control>();
// getting existent controls that will be inflated in modal
Control mContext = (Control) context.Instance;
GetControls(mContext);
// open form and get response
CollectionDesign<Control> frmCollections = new CollectionDesign<Control>(mControls, ref mPickedControls);
var response = _editorService.ShowDialog(frmCollections);
// returning data from editor
return response == DialogResult.OK ? mPickedControls : value;
}
这里一切正常。我在BaseForm 中的变量代码。 Ps.:这个变量将显示在MyForm 上,我点击省略号 [...]
[Editor(typeof(CollectionTypeEditor), typeof(UITypeEditor))]
[TypeConverter(typeof(ActionButtonConverter))]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public List<Control> ActionButtons { get; set; }
添加了序列化属性,因为无法保存文件。当表单关闭并重新打开时,所有数据都将丢失。
奇怪的是我写了其他 UITypeEditor 就像 同样的方式,只是将数据类型更改为string,我可以关闭或重新打开我的表单,一切正常,数据被保存.
我已经添加了一个 TypeConverter,但我认为这不是这里的情况。我的代码有什么问题?
我在重新打开表单时收到此错误:
Severity Code Description Project File Line Suppression State Message Method 'System.CodeDom.CodePropertyReferenceExpression.Add' not found.
更新
现在我的控件列表在关闭或重新打开时存储在 myForm.designer 文件中,但控件未附加到属性网格上。即:如果我在关闭并重新打开 myForm 时单击省略号添加按钮“addbt”,则代码会自动生成。
myForm.designer 上自动生成的代码如下:
//
// addbt
//
this.addbt.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.addbt.Cursor = System.Windows.Forms.Cursors.Hand;
this.addbt.Font = new System.Drawing.Font("Tahoma", 9F);
this.addbt.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(222)))), ((int)(((byte)(0)))), ((int)(((byte)(0)))), ((int)(((byte)(0)))));
this.addbt.Location = new System.Drawing.Point(13, 6);
this.addbt.Name = "addbt";
this.addbt.Size = new System.Drawing.Size(103, 33);
this.addbt.TabIndex = 0;
this.addbt.Text = "Incluir";
this.addbt.UseVisualStyleBackColor = true;
//
// myForm
//
this.ActionButtons.Add(this.addbt);
如果我再次单击省略号,数据将附加到 myForm 的 PropertyGrid 上的属性。但是当我重新打开 myForm 时,之前存储的这些值不会传递给 myForm 的 PropertyGrid 上的属性(数据仍存储在自动生成的代码设计器中)。因此,当单击省略号 [...] 时,value 中的 EditValue 方法不会存储数据。我觉得它更接近了:)
下面的 TypeConverter 可能有问题:
public class ActionButtonConverter : TypeConverter {
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) {
if (sourceType == (typeof(string)))
return true;
return base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) {
if(value.GetType() == typeof(string)) {
List<Control> ctrs = value as List<Control>;
if (ctrs != null)
return ctrs;
}
return base.ConvertFrom(context, culture, value);
}
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) {
if (destinationType == typeof(string))
return true;
return base.CanConvertTo(context, destinationType);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) {
if (value == null)
return "null";
if (destinationType == typeof(string))
return "(custom collection)";
return base.ConvertTo(context, culture, value, destinationType);
}
我认为我在反序列化中有任何错误。当 myForm 重新打开时,ITypeDescriptorContext 或值 (TypeConverter) 没有任何关于序列化数据到 Designer.cs 文件中的信息。
谢谢大家,抱歉语言不好:P
【问题讨论】:
-
我不太明白发生了什么。当您重新打开表单时,您在属性网格中看到了什么?当您单击省略号按钮时,您的表单设计器是填充的还是空的?
-
@Sefe 当我打开表单时,属性网格中的变量为空,但
NameForm.Designer.cs文件已正确保存数据,就像我在 UPDATE 部分中显示的那样。那是序列化问题还是 TypeConverter 问题? -
当你打开你的编辑器时,它会显示所有添加的控件吗?如果是,则可能是类型编辑器问题。在这种情况下,您应该确保您的列表正确转换为字符串。如果没有,您可能需要查看您的 serialilzer 的反序列化方法。
-
@Sefe 如果您说的编辑器与 myForm 相同,那么是的,所有控件都会添加。如果不是,则该编辑器是 typeof(CustomTypeEditor) 然后不是(未添加控件)。你能告诉我如何序列化/反序列化这些数据或编写一个基本示例,如包含两个项目的列表吗?我应该放什么课?我将在更新部分发布我的 TypeEditor。
标签: c# winforms design-time uitypeeditor