如何创建自定义控件属性作为表单,并且属性具有项目中所有表单的选项?

问题描述 投票:1回答:2

我正在使用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
c# .net vb.net winforms windows-forms-designer
2个回答
0
投票

有两种服务可以帮助您在设计时发现和解决解决方案中的所有类型:

另一方面,要在属性编辑器的下拉列表中显示标准值,您可以创建一个TypeConverter

  • TypeConverter:提供将值类型转换为其他类型以及访问标准值和子属性的统一方法。

了解上述选项后,您可以创建自定义类型转换器以发现项目中的所有表单类型并在下拉列表中列出。

在下面的示例中,我创建了一个自定义按钮类,允许您在设计类型中选择一种表单类型,然后在运行时,如果单击该按钮,它会将所选表单显示为对话框:

enter image description here

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

0
投票

假设一个字符串属性对你来说足够好,在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
© www.soinside.com 2019 - 2024. All rights reserved.