如何创建自定义消息框?

14

我正在尝试使用自定义控件来创建一个消息框。

public static partial class Msg : Form
{
    public static void show(string content, string description)
    {

    }
}

实际上,我需要在这个窗体中放置一些控件(一个网格视图),并且我必须为此窗口应用自己的主题,因此我不想使用MessageBox。 我想从我的其他窗体中调用它。

Msg.show(parameters);

我不想为这个表单创建一个对象。

我知道我不能从Form类继承,因为它不是静态的。但我想知道MessageBox是如何实现的,因为它是静态的。它被调用的方式就像MessageBox.show("Some message!");

现在我得到了一个错误,因为不允许继承:

  

静态类'MyFormName'不能派生自类型'System.Windows.Forms.Form'。静态类必须从对象派生

我的表单截图

那么MessageBox是如何实现的呢?


3
.NET的MessageBox只是Win32框架中MessageBox的一个包装器。为了创建自定义的MessageBox,你需要创建一个Form对象。可以考虑将其设计成单例模式,也可以每次调用“Msg.Show()”时创建一个新的Form对象并立即显示,然后再销毁它。 - Matt Greer
2
Msg类不必为静态的,show方法可以是静态的。 - Joe
4个回答

26

你的表单类不需要是 static 的。事实上,一个 static 类根本无法继承

相反地,创建一个从 Form 派生的内部表单类,并提供一个公共静态辅助方法来显示它

如果你不希望调用者甚至“知道”底层表单的情况下,此静态方法可以在另一个类中定义

/// <summary>
/// The form internally used by <see cref="CustomMessageBox"/> class.
/// </summary>
internal partial class CustomMessageForm : Form
{
    /// <summary>
    /// This constructor is required for designer support.
    /// </summary>
    public CustomMessageForm ()
    {
        InitializeComponent(); 
    } 

    public CustomMessageForm (string title, string description)
    {
        InitializeComponent(); 

        this.titleLabel.Text = title;
        this.descriptionLabel.Text = description;
    } 
}

/// <summary>
/// Your custom message box helper.
/// </summary>
public static class CustomMessageBox
{
    public static void Show (string title, string description)
    {
        // using construct ensures the resources are freed when form is closed
        using (var form = new CustomMessageForm (title, description)) {
            form.ShowDialog ();
        }
    }
}

顺带一提:正如Jalal指出的,为了拥有静态方法,你并不需要把整个类都设置为static。但我仍然建议将“辅助”类与实际表单分开,这样调用者就无法使用构造函数创建表单(当然,如果它们在同一个程序集中,则可以)。


感谢您的快速回复。我已经完成了这个表单。谢谢Dan Abramov提供不同的答案,使用了内部类 :) - Sen Jacob
是的,通过使用这个内部类,我可以避免调用构造函数,这对我来说是一个新概念...再次感谢你的解释。 - Sen Jacob
1
是的,但这仅在您将这些类定义在单独的程序集中时才有效。另一个选项是在静态帮助器内声明Form类并将其声明为private,但这样会失去设计器,所以我认为这不值得。 - Dan Abramov
1
使用 (var form = new CustomMessageForm(title, description)) { form.ShowDialog(); } 你能解释一下为什么要使用 var 吗?.......... new CustomMessageForm(title, description).ShowDialog(); 这段代码有没有问题,是一个良好编写的代码吗?抱歉,我没有太多机会学习这些概念。我只想学习这些最佳实践。 - Sen Jacob
1
@BeediKumaraN: var可以让编译器为你推断类型,这样你就不必再写一遍类型名称CustomMessageForm form = new CustomMessageForm。我建议你先谷歌一下,并且阅读这个讨论帖子。通常,请单独发布一个新问题,而不是在评论中进行讨论。 - Dan Abramov
如果我想在这个自定义消息框中创建两个按钮(确定,取消),我该如何获取按下哪个按钮来终止消息框?我尝试从Show方法返回一个DialogResult,但它会导致非静态成员出现问题。 - TmZn

5
您不需要将类设置为静态的。 只需执行以下操作:
public partial class Msg : Form
{
    public static void show(string content, string description)
    {
         Msg message = new Msg(...);
         message.show();
    }
}

4
-1是因为您没有释放资源(而且 Show 不是模态的,您应该调用 ShowDialog)。 - Dan Abramov

2
你不需要将类声明为static才能静态调用其中的方法,只需将特定的方法声明为static即可。
public partial class DetailedMessageBox : Form
{
    public DetailedMessageBox()
    {
        InitializeComponent();
    }

    public static void ShowMessage(string content, string description)
    {
        DetailedMessageBox messageBox = new DetailedMessageBox();
        messageBox.ShowDialog();
    }
}

我们正在使用messageBox.ShowDialog()将表单显示为一个模态窗口。您可以使用DetailedMessageBox.ShowMessage("内容", "描述");来显示消息框。
顺便说一下,您应该重新考虑您的命名并坚持一致的命名模式。 Msgshow是弱名称,不符合命名指南 - 您肯定想要查看这些!

好的,我会检查那些命名规范。谢谢你指出来。 - Sen Jacob

-2
在WPF项目中,您可以添加一个新窗口并将其命名为MessageBoxCustom,然后在C#中的Void中,您可以找到InitialiseComponent(); 添加2个属性,并将这些属性绑定到您应该在XAML视图中创建的textBlocks。 例如:
public MessageBoxCustom(string Message, string Title)
{
    InitialiseComponent();//this comes first to load Front End
    textblock1.Text = Title;
    textblock2.Text = Message;
}

Just position your TextBlocks where you want them to be displayed in XAML


From your Main Window you can call that message box like this


private void Button_Click()
{
    MessageBoxCustom msg = new MessageBoxCustom("Your message here","Your title her");
    msg.ShowDialog();
}

在一个WPF项目中 - 是的,但是答案明显标记为formswinforms - Thomas Flinkow

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接