我正在使用VB.Net开发一个winform项目。在这个项目中,我使自定义按钮继承自UserControl并将FormName属性添加为Form。这样我就可以为FormName属性分配单击自定义按钮时程序将打开的表单。该属性实际上显示在Visual Studio Property Panel中,但仅显示表单本身作为唯一选项,我们无法从同一项目中选择其他表单。
这是该属性的代码
<Browsable(True), Description("Set the Form Name")> Public Property FormName As Form
Get
Return _formName
End Get
Set(ByVal value As Form)
_formName = value
End Set
End Property
我试图将上面的属性更改为String并以字符串格式键入Form Name。之后,我创建了一个openForm函数来通过接收String作为参数来打开表单,因此基本上获取字符串Form Name并创建表单的新实例。但最后,我遇到了与表单控件(如文本框)交互的问题,因为表单有两个实例。所以我放弃了这个想法。
这是我的openForm函数的代码,用于从String Name打开表单:
Public Function openForm(ByVal frm As String, Optional ByVal focusCtrl As Control = Nothing, Optional ByVal isFullscreen As Boolean = True, Optional ByVal isDialog As Boolean = False) As Form
Dim obj As Form = TryCast(Activator.CreateInstance(Type.GetType("Management_System." + frm)), Form)
Dim myAnimator As New FormAnimator(obj, FormAnimator.AnimationTypes.Blend, fadingTime)
obj.StartPosition = FormStartPosition.CenterScreen
If isDialog Then
obj.ShowDialog()
focusCtrl.Focus()
Else
Dim frms = Application.OpenForms
Dim isOpened As Boolean = False
For Each q In frms
If q.GetType().Name = obj.Name Then
obj = CType(q, Form)
isOpened = True
Exit For
Else
isOpened = False
End If
Next
If isOpened = True Then
If isFullscreen Then
obj.WindowState = FormWindowState.Maximized
Else
obj.WindowState = FormWindowState.Normal
End If
If obj.Visible Then
obj.BringToFront()
Else
obj.Show()
End If
Else
obj.Show()
obj.BringToFront()
End If
End If
Return obj
End Function
预期输出是作为表单的自定义控件属性,其中包含项目中所有表单的选项。
请帮助解决这个问题。提前致谢
编辑:
Private Sub Button_Click(sender As Object, e As EventArgs) Handles cbtnPurchase.Click, cbtnPurchaseReturn.Click, cbtnSales.Click, cbtnSalesReturn.Click, cbtnMutationIn.Click, cbtnMutationOut.Click, cbtnSwitchWarehouse.Click, cbtnOpname.Click, cbtnCakery.Click
Try
Dim btn As customButton = CType(sender, customButton)
If ExitForm Then Return
openForm(btn.FormName)
Catch ex As Exception
MsgTryCatch(ex.Message)
End Try
End Sub
有两种服务可以帮助您在设计时发现和解决解决方案中的所有类型:
ITypeDiscoveryService
:在设计时发现可用的类型。ITypeResolutionService
:提供用于按名称检索程序集或类型的接口。另一方面,要在属性编辑器的下拉列表中显示标准值,您可以创建一个TypeConverter
:
TypeConverter
:提供将值类型转换为其他类型以及访问标准值和子属性的统一方法。了解上述选项后,您可以创建自定义类型转换器以发现项目中的所有表单类型并在下拉列表中列出。
例
在下面的示例中,我创建了一个自定义按钮类,允许您在设计类型中选择一种表单类型,然后在运行时,如果单击该按钮,它会将所选表单显示为对话框:
为myButton
using System;
using System.ComponentModel;
using System.Windows.Forms;
public class MyButton : Button
{
[TypeConverter(typeof(FormTypeConverter))]
public Type Form { get; set; }
protected override void OnClick(EventArgs e)
{
base.OnClick(e);
if (Form != null && typeof(Form).IsAssignableFrom(Form))
{
using (var f = (Form)Activator.CreateInstance(Form))
f.ShowDialog();
}
}
}
FormTypeConverter
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Globalization;
using System.Linq;
using System.Windows.Forms;
public class FormTypeConverter : TypeConverter
{
public override bool GetStandardValuesExclusive
(ITypeDescriptorContext context)
{
return true;
}
public override bool CanConvertTo
(ITypeDescriptorContext pContext, Type pDestinationType)
{
return base.CanConvertTo(pContext, pDestinationType);
}
public override object ConvertTo
(ITypeDescriptorContext pContext, CultureInfo pCulture,
object pValue, Type pDestinationType)
{
return base.ConvertTo(pContext, pCulture, pValue, pDestinationType);
}
public override bool CanConvertFrom(ITypeDescriptorContext pContext,
Type pSourceType)
{
if (pSourceType == typeof(string))
return true;
return base.CanConvertFrom(pContext, pSourceType);
}
public override object ConvertFrom
(ITypeDescriptorContext pContext, CultureInfo pCulture, object pValue)
{
if (pValue is string)
return GetTypeFromName(pContext, (string)pValue);
return base.ConvertFrom(pContext, pCulture, pValue);
}
public override bool GetStandardValuesSupported
(ITypeDescriptorContext pContext)
{
return true;
}
public override StandardValuesCollection GetStandardValues
(ITypeDescriptorContext pContext)
{
List<Type> types = GetProjectTypes(pContext);
List<string> values = new List<string>();
foreach (Type type in types)
values.Add(type.FullName);
values.Sort();
return new StandardValuesCollection(values);
}
private List<Type> GetProjectTypes(IServiceProvider serviceProvider)
{
var typeDiscoverySvc = (ITypeDiscoveryService)serviceProvider
.GetService(typeof(ITypeDiscoveryService));
var types = typeDiscoverySvc.GetTypes(typeof(object), true)
.Cast<Type>()
.Where(item =>
item.IsPublic &&
typeof(Form).IsAssignableFrom(item) &&
!item.FullName.StartsWith("System")
).ToList();
return types;
}
private Type GetTypeFromName(IServiceProvider serviceProvider, string typeName)
{
ITypeResolutionService typeResolutionSvc = (ITypeResolutionService)serviceProvider
.GetService(typeof(ITypeResolutionService));
return typeResolutionSvc.GetType(typeName);
}
}
假设一个字符串属性对你来说足够好,在VB.NET项目中,你可以依赖My.Forms
并按名称获取表单并显示它:
Public Class MyButton
Inherits Button
Public Property Form As String
Protected Overrides Sub OnClick(e As EventArgs)
If (Not String.IsNullOrEmpty(Form)) Then
Dim fp = My.Forms.GetType().GetProperty(Form)
If (fp IsNot Nothing) Then
Dim f = fp.GetValue(My.Forms)
DirectCast(f, Form).ShowDialog()
End If
End If
MyBase.OnClick(e)
End Sub
End Class