Okno dialogowe monitu w Windows Forms

115

Używam, System.Windows.Formsale o dziwo nie mam możliwości ich tworzenia.

Jak mogę uzyskać coś takiego jak okno dialogowe z monitem javascript, bez javascript?

MessageBox jest fajny, ale użytkownik nie ma możliwości wprowadzenia danych wejściowych.

Chcę, aby użytkownik wprowadzał dowolny możliwy tekst.

user420667
źródło
Czy możesz zamieścić przykładowy kod tego, co próbujesz zrobić?
Andrew Cooper,
Jakiego rodzaju danych szukasz, podaj trochę więcej szczegółów. CommonDialog Spójrz na klasy, które go dziedziczą, czy któraś z nich wygląda dobrze dla Ciebie?
Sanjeevakumar Hiremath
21
To zabawne, jak trzy osoby proszą OP o więcej szczegółów i próbek kodu, ale jest całkiem jasne, co ma na myśli, mówiąc „jak okno dialogowe zachęty do javascript” .
Camilo Martin,
2
Oto dwa przykłady, jeden podstawowy, a drugi z walidacją danych wejściowych: 1. basic - csharp-examples.net/inputbox 2. validation - csharp-examples.net/inputbox-class
JasonM1

Odpowiedzi:

274

Musisz utworzyć własne okno dialogowe Monit. Być może mógłbyś stworzyć do tego klasę.

public static class Prompt
{
    public static string ShowDialog(string text, string caption)
    {
        Form prompt = new Form()
        {
            Width = 500,
            Height = 150,
            FormBorderStyle = FormBorderStyle.FixedDialog,
            Text = caption,
            StartPosition = FormStartPosition.CenterScreen
        };
        Label textLabel = new Label() { Left = 50, Top=20, Text=text };
        TextBox textBox = new TextBox() { Left = 50, Top=50, Width=400 };
        Button confirmation = new Button() { Text = "Ok", Left=350, Width=100, Top=70, DialogResult = DialogResult.OK };
        confirmation.Click += (sender, e) => { prompt.Close(); };
        prompt.Controls.Add(textBox);
        prompt.Controls.Add(confirmation);
        prompt.Controls.Add(textLabel);
        prompt.AcceptButton = confirmation;

        return prompt.ShowDialog() == DialogResult.OK ? textBox.Text : "";
    }
}

I nazywając to:

string promptValue = Prompt.ShowDialog("Test", "123");

Aktualizacja :

Dodano przycisk domyślny ( klawisz Enter ) i początkowy fokus oparty na komentarzach i innym pytaniu .

Bas
źródło
1
Jak rozszerzyć to na A) mieć przycisk anulowania i B) w jakiś sposób zweryfikować tekst w polu tekstowym przed powrotem?
ewok
@ewok Po prostu utwórz formularz, Projektant formularzy pomoże Ci ułożyć go tak, jak chcesz.
Camilo Martin,
1
@SeanWorle Nie widzę, gdzie o tym wspomniano.
Bas
1
Osiągnąłem to, dodając: prompt.AcceptButton = potwierdzenie;
B. Clay Shannon
1
Dodano kod do obsługi anulowania monitu przez użytkownika za pomocą przycisku zamykania i zwrócenia pustego ciągu
Matthew Lock
53

Dodaj odniesienie do Microsoft.VisualBasici użyj tego w swoim kodzie C #:

string input = Microsoft.VisualBasic.Interaction.InputBox("Prompt", 
                       "Title", 
                       "Default", 
                       0, 
                       0);

Aby dodać odniesienie: kliknij prawym przyciskiem myszy References w oknie Project Explorer, a następnie Add Reference i zaznacz VisualBasic z tej listy.

KurvaBG
źródło
4
To mówi, Interactionże nie istnieje w przestrzeni nazwMicrosoft.VisualBasic
Khalil Khalaf,
1
jest to nieco lepsze niż rozwiązanie klasy niestandardowej, ponieważ obsługuje ekrany o wysokiej rozdzielczości
zaznacz gamache
Wiem, że prawdopodobnie użycie niestandardowego rozwiązania byłoby lepsze, ale szukam szybkiego i łatwego rozwiązania, a to było najlepsze. Serdecznie dziękuję wszystkim.
Juano
14

W Windows Forms nie ma czegoś takiego natywnie.

W tym celu musisz stworzyć własny formularz lub:

użyj Microsoft.VisualBasicodniesienia.

Inputbox to starszy kod wprowadzony do .Net w celu zapewnienia zgodności z VB6 - więc radzę tego nie robić.

Marino Šimić
źródło
2
Dotyczy to Microsoft.VisualBasic.Compatibilityprzestrzeni nazw. Microsoft.VisualBasicjest raczej zestawem bibliotek pomocniczych na wierzchu .Net i nie jest tak naprawdę specyficzny dla VB.
Jim Wooley
-1 z powodu niedokładnego oświadczenia o odwołaniu do VB. Nie ma powodu, aby odstraszyć ludzi od korzystania z tej bardzo przydatnej wbudowanej funkcji.
UuDdLrLrSs
6

Generalnie nie jest dobrym pomysłem importowanie bibliotek VisualBasic do programów C # (nie dlatego, że nie będą działać, ale tylko ze względu na zgodność, styl i możliwość aktualizacji), ale możesz wywołać Microsoft.VisualBasic.Interaction.InputBox () aby wyświetlić rodzaj pudełka, którego szukasz.

Jeśli możesz utworzyć obiekt Windows.Forms, byłoby najlepiej, ale mówisz, że nie możesz tego zrobić.

Sean Worle
źródło
26
Dlaczego to nie jest dobry pomysł? Jakie są możliwe problemy z „zgodnością” i „możliwością aktualizacji”? Zgadzam się, że mówiąc „stylistycznie”, większość programistów C # wolałaby nie używać klas z nazwanej przestrzeni nazw VisualBasic, ale to tylko w ich głowie. To uczucie nie ma rzeczywistości. Równie dobrze można by to nazwać Microsoft.MakeMyLifeEasierWithAlreadyImplementedMethodsprzestrzenią nazw.
Cody Gray
3
Ogólnie pakiet Microsoft.VisualBasic ma na celu uproszczenie aktualizacji kodu tylko z VB 6. Microsoft wciąż grozi trwałym wygaśnięciem VB (choć prawdopodobnie nigdy się to nie wydarzy), więc przyszłe wsparcie dla tej przestrzeni nazw nie jest gwarantowane. Dodatkowo jedną z zalet .Net ma być przenośność - ten sam kod będzie działał na każdej platformie, na której jest zainstalowany framework .Net. Nie ma jednak gwarancji, że Microsoft.VisualBasic będzie dostępny na żadnej innej platformie (w tym, co jest warte, .Net mobile, gdzie w ogóle nie jest dostępny).
Sean Worle
22
Błędny. To jest Microsoft.VisualBasic.Compatibilitypodprzestrzeń nazw, a nie cała sprawa. Przestrzeń Microsoft.VisualBasicnazw zawiera wiele „podstawowych” funkcji ; nigdzie się nie wybiera. Microsoft zagroził „wygaśnięciem” VB 6, a nie VB.NET. Wielokrotnie obiecywali , że nigdzie się nie wybiera. Niektórzy ludzie nadal nie zdawali sobie sprawy z różnicy ...
Cody Gray
4

Inny sposób na zrobienie tego: Zakładając, że masz typ wejściowy TextBox, Utwórz formularz i masz wartość pola tekstowego jako właściwość publiczną.

public partial class TextPrompt : Form
{
    public string Value
    {
        get { return tbText.Text.Trim(); }
    }

    public TextPrompt(string promptInstructions)
    {
        InitializeComponent();

        lblPromptText.Text = promptInstructions;
    }

    private void BtnSubmitText_Click(object sender, EventArgs e)
    {
        Close();
    }

    private void TextPrompt_Load(object sender, EventArgs e)
    {
        CenterToParent();
    }
}

W głównej formie będzie to kod:

var t = new TextPrompt(this, "Type the name of the settings file:");
t.ShowDialog()

;

W ten sposób kod wygląda na bardziej przejrzysty:

  1. Jeśli dodano logikę walidacji.
  2. Jeśli dodano różne inne typy wejść.
user2347528
źródło
4

Odpowiedź Bas może teoretycznie wprowadzić Cię w kłopoty z pamięcią, ponieważ ShowDialog nie zostanie usunięty. Myślę, że to bardziej właściwy sposób. Wspomnij również o czytelności textLabel z dłuższym tekstem.

public class Prompt : IDisposable
{
    private Form prompt { get; set; }
    public string Result { get; }

    public Prompt(string text, string caption)
    {
        Result = ShowDialog(text, caption);
    }
    //use a using statement
    private string ShowDialog(string text, string caption)
    {
        prompt = new Form()
        {
            Width = 500,
            Height = 150,
            FormBorderStyle = FormBorderStyle.FixedDialog,
            Text = caption,
            StartPosition = FormStartPosition.CenterScreen,
            TopMost = true
        };
        Label textLabel = new Label() { Left = 50, Top = 20, Text = text, Dock = DockStyle.Top, TextAlign = ContentAlignment.MiddleCenter };
        TextBox textBox = new TextBox() { Left = 50, Top = 50, Width = 400 };
        Button confirmation = new Button() { Text = "Ok", Left = 350, Width = 100, Top = 70, DialogResult = DialogResult.OK };
        confirmation.Click += (sender, e) => { prompt.Close(); };
        prompt.Controls.Add(textBox);
        prompt.Controls.Add(confirmation);
        prompt.Controls.Add(textLabel);
        prompt.AcceptButton = confirmation;

        return prompt.ShowDialog() == DialogResult.OK ? textBox.Text : "";
    }

    public void Dispose()
    {
        //See Marcus comment
        if (prompt != null) { 
            prompt.Dispose(); 
        }
    }
}

Realizacja:

using(Prompt prompt = new Prompt("text", "caption")){
    string result = prompt.Result;
}
Gideon Mulder
źródło
2
Dobre wykorzystanie zarządzania pamięcią. Ale kończy się to niepowodzeniem podczas dodawania przycisku anulowania, ponieważ promptw tym momencie jest on pusty. Prosty fix, aby umożliwić anulowanie monit ma zastąpić prompt.Dispose();wnętrze public void Dispose()zif (prompt != null) { prompt.Dispose(); }
Marcus Parsons
3

Opierając się na powyższej pracy Bas Brekelmans, stworzyłem również dwie derywacje -> okna dialogowe „wejściowe”, które umożliwiają otrzymanie od użytkownika zarówno wartości tekstowej, jak i wartości logicznej (TextBox i CheckBox):

public static class PromptForTextAndBoolean
{
    public static string ShowDialog(string caption, string text, string boolStr)
    {
        Form prompt = new Form();
        prompt.Width = 280;
        prompt.Height = 160;
        prompt.Text = caption;
        Label textLabel = new Label() { Left = 16, Top = 20, Width = 240, Text = text };
        TextBox textBox = new TextBox() { Left = 16, Top = 40, Width = 240, TabIndex = 0, TabStop = true };
        CheckBox ckbx = new CheckBox() { Left = 16, Top = 60, Width = 240, Text = boolStr };
        Button confirmation = new Button() { Text = "Okay!", Left = 16, Width = 80, Top = 88, TabIndex = 1, TabStop = true };
        confirmation.Click += (sender, e) => { prompt.Close(); };
        prompt.Controls.Add(textLabel);
        prompt.Controls.Add(textBox);
        prompt.Controls.Add(ckbx);
        prompt.Controls.Add(confirmation);
        prompt.AcceptButton = confirmation;
        prompt.StartPosition = FormStartPosition.CenterScreen;
        prompt.ShowDialog();
        return string.Format("{0};{1}", textBox.Text, ckbx.Checked.ToString());
    }
}

... i tekst wraz z wyborem jednej z wielu opcji (TextBox i ComboBox):

public static class PromptForTextAndSelection
{
    public static string ShowDialog(string caption, string text, string selStr)
    {
        Form prompt = new Form();
        prompt.Width = 280;
        prompt.Height = 160;
        prompt.Text = caption;
        Label textLabel = new Label() { Left = 16, Top = 20, Width = 240, Text = text };
        TextBox textBox = new TextBox() { Left = 16, Top = 40, Width = 240, TabIndex = 0, TabStop = true };
        Label selLabel = new Label() { Left = 16, Top = 66, Width = 88, Text = selStr };
        ComboBox cmbx = new ComboBox() { Left = 112, Top = 64, Width = 144 };
        cmbx.Items.Add("Dark Grey");
        cmbx.Items.Add("Orange");
        cmbx.Items.Add("None");
        Button confirmation = new Button() { Text = "In Ordnung!", Left = 16, Width = 80, Top = 88, TabIndex = 1, TabStop = true };
        confirmation.Click += (sender, e) => { prompt.Close(); };
        prompt.Controls.Add(textLabel);
        prompt.Controls.Add(textBox);
        prompt.Controls.Add(selLabel);
        prompt.Controls.Add(cmbx);
        prompt.Controls.Add(confirmation);
        prompt.AcceptButton = confirmation;
        prompt.StartPosition = FormStartPosition.CenterScreen;
        prompt.ShowDialog();
        return string.Format("{0};{1}", textBox.Text, cmbx.SelectedItem.ToString());
    }
}

Oba wymagają tych samych zastosowań:

using System;
using System.Windows.Forms;

Nazwij ich tak:

Nazwij ich tak:

PromptForTextAndBoolean.ShowDialog("Jazz", "What text should accompany the checkbox?", "Allow Scat Singing"); 

PromptForTextAndSelection.ShowDialog("Rock", "What should the name of the band be?", "Beret color to wear");
B. Clay Shannon
źródło
2

Odpowiedź Bas Brekelmans jest bardzo elegancka w swojej prostocie. Ale okazało się, że do rzeczywistej aplikacji potrzeba trochę więcej, na przykład:

  • Rozwijaj formularz odpowiednio, gdy tekst wiadomości jest zbyt długi.
  • Nie wyskakuje automatycznie na środku ekranu.
  • Nie zapewnia żadnej weryfikacji danych wejściowych użytkownika.

Klasa tutaj obsługuje te ograniczenia: http://www.codeproject.com/Articles/31315/Getting-User-Input-With-Dialogs-Part-1

Właśnie pobrałem źródło i skopiowałem InputBox.cs do mojego projektu.

Zaskoczony, że nie ma czegoś nawet lepszego ... Moją jedyną prawdziwą skargą jest to, że tekst podpisu nie obsługuje znaków nowych linii, ponieważ używa kontrolki etykiety.

blak3r
źródło
Ładna odpowiedź, ale poza zakresem
zadanego
1

Niestety C # nadal nie oferuje tej możliwości we wbudowanych bibliotekach. Obecnie najlepszym rozwiązaniem jest utworzenie własnej klasy za pomocą metody wyświetlającej mały formularz. Jeśli pracujesz w programie Visual Studio, możesz to zrobić, klikając projekt> Dodaj klasę

Dodaj klasę

Elementy wizualne C #> kod> klasa Dodaj klasę 2

Nazwij klasę PopUpBox (możesz zmienić jej nazwę później, jeśli chcesz) i wklej następujący kod:

using System.Drawing;
using System.Windows.Forms;

namespace yourNameSpaceHere
{
    public class PopUpBox
    {
        private static Form prompt { get; set; }

        public static string GetUserInput(string instructions, string caption)
        {
            string sUserInput = "";
            prompt = new Form() //create a new form at run time
            {
                Width = 500, Height = 150, FormBorderStyle = FormBorderStyle.FixedDialog, Text = caption,
                StartPosition = FormStartPosition.CenterScreen, TopMost = true
            };
            //create a label for the form which will have instructions for user input
            Label lblTitle = new Label() { Left = 50, Top = 20, Text = instructions, Dock = DockStyle.Top, TextAlign = ContentAlignment.TopCenter };
            TextBox txtTextInput = new TextBox() { Left = 50, Top = 50, Width = 400 };

            ////////////////////////////OK button
            Button btnOK = new Button() { Text = "OK", Left = 250, Width = 100, Top = 70, DialogResult = DialogResult.OK };
            btnOK.Click += (sender, e) => 
            {
                sUserInput = txtTextInput.Text;
                prompt.Close();
            };
            prompt.Controls.Add(txtTextInput);
            prompt.Controls.Add(btnOK);
            prompt.Controls.Add(lblTitle);
            prompt.AcceptButton = btnOK;
            ///////////////////////////////////////

            //////////////////////////Cancel button
            Button btnCancel = new Button() { Text = "Cancel", Left = 350, Width = 100, Top = 70, DialogResult = DialogResult.Cancel };
            btnCancel.Click += (sender, e) => 
            {
                sUserInput = "cancel";
                prompt.Close();
            };
            prompt.Controls.Add(btnCancel);
            prompt.CancelButton = btnCancel;
            ///////////////////////////////////////

            prompt.ShowDialog();
            return sUserInput;
        }

        public void Dispose()
        {prompt.Dispose();}
    }
}

Będziesz musiał zmienić przestrzeń nazw na dowolną, której używasz. Metoda zwraca ciąg, więc oto przykład, jak zaimplementować ją w metodzie wywołującej:

bool boolTryAgain = false;

do
{
    string sTextFromUser = PopUpBox.GetUserInput("Enter your text below:", "Dialog box title");
    if (sTextFromUser == "")
    {
        DialogResult dialogResult = MessageBox.Show("You did not enter anything. Try again?", "Error", MessageBoxButtons.YesNo);
        if (dialogResult == DialogResult.Yes)
        {
            boolTryAgain = true; //will reopen the dialog for user to input text again
        }
        else if (dialogResult == DialogResult.No)
        {
            //exit/cancel
            MessageBox.Show("operation cancelled");
            boolTryAgain = false;
        }//end if
    }
    else
    {
        if (sTextFromUser == "cancel")
        {
            MessageBox.Show("operation cancelled");
        }
        else
        {
            MessageBox.Show("Here is the text you entered: '" + sTextFromUser + "'");
            //do something here with the user input
        }

    }
} while (boolTryAgain == true);

Ta metoda sprawdza zwrócony ciąg znaków pod kątem wartości tekstowej, pustego ciągu lub „anuluj” (metoda getUserInput zwraca „anuluj” po kliknięciu przycisku anulowania) i działa odpowiednio. Jeśli użytkownik nic nie wprowadził i kliknął OK, poinformuje o tym użytkownika i zapyta, czy chce anulować, czy ponownie wprowadzić tekst.

Notatki: w mojej własnej implementacji stwierdziłem, że we wszystkich pozostałych odpowiedziach brakowało 1 lub więcej z następujących odpowiedzi:

  • Przycisk anulowania
  • Możliwość zawarcia symboli w ciągu przesyłanym do metody
  • Jak uzyskać dostęp do metody i obsługiwać zwróconą wartość.

Dlatego zamieściłem własne rozwiązanie. Mam nadzieję, że ktoś uzna to za przydatne. Podziękowania dla komentujących Bas i Gideon + za wasze uwagi, pomogliście mi znaleźć praktyczne rozwiązanie!

technoman23
źródło
0

oto moja refaktoryzowana wersja, która akceptuje multiline / single jako opcję

   public string ShowDialog(string text, string caption, bool isMultiline = false, int formWidth = 300, int formHeight = 200)
        {
            var prompt = new Form
            {
                Width = formWidth,
                Height = isMultiline ? formHeight : formHeight - 70,
                FormBorderStyle = isMultiline ? FormBorderStyle.Sizable : FormBorderStyle.FixedSingle,
                Text = caption,
                StartPosition = FormStartPosition.CenterScreen,
                MaximizeBox = isMultiline
            };

            var textLabel = new Label
            {
                Left = 10,
                Padding = new Padding(0, 3, 0, 0),
                Text = text,
                Dock = DockStyle.Top
            };

            var textBox = new TextBox
            {
                Left = isMultiline ? 50 : 4,
                Top = isMultiline ? 50 : textLabel.Height + 4,
                Multiline = isMultiline,
                Dock = isMultiline ? DockStyle.Fill : DockStyle.None,
                Width = prompt.Width - 24,
                Anchor = isMultiline ? AnchorStyles.Left | AnchorStyles.Top : AnchorStyles.Left | AnchorStyles.Right
            };

            var confirmationButton = new Button
            {
                Text = @"OK",
                Cursor = Cursors.Hand,
                DialogResult = DialogResult.OK,
                Dock = DockStyle.Bottom,
            };

            confirmationButton.Click += (sender, e) =>
            {
                prompt.Close();
            };

            prompt.Controls.Add(textBox);
            prompt.Controls.Add(confirmationButton);
            prompt.Controls.Add(textLabel);

            return prompt.ShowDialog() == DialogResult.OK ? textBox.Text : string.Empty;
        }
Alper Ebicoglu
źródło
-2

Oto przykład w VB.NET

Public Function ShowtheDialog(caption As String, text As String, selStr As String) As String
    Dim prompt As New Form()
    prompt.Width = 280
    prompt.Height = 160
    prompt.Text = caption
    Dim textLabel As New Label() With { _
         .Left = 16, _
         .Top = 20, _
         .Width = 240, _
         .Text = text _
    }
    Dim textBox As New TextBox() With { _
         .Left = 16, _
         .Top = 40, _
         .Width = 240, _
         .TabIndex = 0, _
         .TabStop = True _
    }
    Dim selLabel As New Label() With { _
         .Left = 16, _
         .Top = 66, _
         .Width = 88, _
         .Text = selStr _
    }
    Dim cmbx As New ComboBox() With { _
         .Left = 112, _
         .Top = 64, _
         .Width = 144 _
    }
    cmbx.Items.Add("Dark Grey")
    cmbx.Items.Add("Orange")
    cmbx.Items.Add("None")
    cmbx.SelectedIndex = 0
    Dim confirmation As New Button() With { _
         .Text = "In Ordnung!", _
         .Left = 16, _
         .Width = 80, _
         .Top = 88, _
         .TabIndex = 1, _
         .TabStop = True _
    }
    AddHandler confirmation.Click, Sub(sender, e) prompt.Close()
    prompt.Controls.Add(textLabel)
    prompt.Controls.Add(textBox)
    prompt.Controls.Add(selLabel)
    prompt.Controls.Add(cmbx)
    prompt.Controls.Add(confirmation)
    prompt.AcceptButton = confirmation
    prompt.StartPosition = FormStartPosition.CenterScreen
    prompt.ShowDialog()
    Return String.Format("{0};{1}", textBox.Text, cmbx.SelectedItem.ToString())
End Function
user890332
źródło