WPF:创建对话框/提示

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2796470/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 21:44:42  来源:igfitidea点击:

WPF: Create a dialog / prompt

wpfxamldialogprompt

提问by stefan.at.wpf

I need to create a Dialog / Prompt including TextBox for user input. My problem is, how to get the text after having confirmed the dialog? Usually I would make a class for this which would save the text in a property. However I want do design the Dialog using XAML. So I would somehow have to extent the XAML Code to save the content of the TextBox in a property - but I guess that's not possible with pure XAML. What would be the best way to realize what I'd like to do? How to build a dialog which can be defined from XAML but can still somehow return the input? Thanks for any hint!

我需要创建一个对话框/提示,包括用于用户输入的 TextBox。我的问题是,确认对话框后如何获取文本?通常我会为此创建一个类,将文本保存在属性中。但是我想使用 XAML 设计对话框。所以我必须以某种方式扩展 XAML 代码以将 TextBox 的内容保存在属性中 - 但我想这对于纯 XAML 是不可能的。实现我想做的事情的最佳方式是什么?如何构建一个可以从 XAML 定义但仍然可以以某种方式返回输入的对话框?感谢您的任何提示!

回答by Josh

The "responsible" answer would be for me to suggest building a ViewModel for the dialog and use two-way databinding on the TextBox so that the ViewModel had some "ResponseText" property or what not. This is easy enough to do but probably overkill.

“负责任”的答案是我建议为对话框构建一个 ViewModel 并在 TextBox 上使用双向数据绑定,以便 ViewModel 具有一些“ResponseText”属性或其他属性。这很容易做到,但可能有点矫枉过正。

The pragmatic answer would be to just give your text box an x:Name so that it becomes a member and expose the text as a property in your code behind class like so:

务实的答案是只给你的文本框一个 x:Name 以便它成为一个成员并将文本作为一个属性暴露在你的类后面的代码中,如下所示:

<!-- Incredibly simplified XAML -->
<Window x:Class="MyDialog">
   <StackPanel>
       <TextBlock Text="Enter some text" />
       <TextBox x:Name="ResponseTextBox" />
       <Button Content="OK" Click="OKButton_Click" />
   </StackPanel>
</Window>

Then in your code behind...

然后在你后面的代码中......

partial class MyDialog : Window {

    public MyDialog() {
        InitializeComponent();
    }

    public string ResponseText {
        get { return ResponseTextBox.Text; }
        set { ResponseTextBox.Text = value; }
    }

    private void OKButton_Click(object sender, System.Windows.RoutedEventArgs e)
    {
        DialogResult = true;
    }
}

Then to use it...

然后使用它...

var dialog = new MyDialog();
if (dialog.ShowDialog() == true) {
    MessageBox.Show("You said: " + dialog.ResponseText);
}

回答by Pythonizo

I just add a static method to call it like a MessageBox:

我只是添加了一个静态方法来像 MessageBox 一样调用它:

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    x:Class="utils.PromptDialog"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    WindowStartupLocation="CenterScreen" 
    SizeToContent="WidthAndHeight"
    MinWidth="300"
    MinHeight="100"
    WindowStyle="SingleBorderWindow"
    ResizeMode="CanMinimize">
<StackPanel Margin="5">
    <TextBlock Name="txtQuestion" Margin="5"/>
    <TextBox Name="txtResponse" Margin="5"/>
    <PasswordBox Name="txtPasswordResponse" />
    <StackPanel Orientation="Horizontal" Margin="5" HorizontalAlignment="Right">
        <Button Content="_Ok" IsDefault="True" Margin="5" Name="btnOk" Click="btnOk_Click" />
        <Button Content="_Cancel" IsCancel="True" Margin="5" Name="btnCancel" Click="btnCancel_Click" />
    </StackPanel>
</StackPanel>
</Window>

And the code behind:

以及背后的代码:

public partial class PromptDialog : Window
{
    public enum InputType
    {
        Text,
        Password
    }

    private InputType _inputType = InputType.Text;

    public PromptDialog(string question, string title, string defaultValue = "", InputType inputType = InputType.Text)
    {
        InitializeComponent();
        this.Loaded += new RoutedEventHandler(PromptDialog_Loaded);
        txtQuestion.Text = question;
        Title = title;
        txtResponse.Text = defaultValue;
        _inputType = inputType;
        if (_inputType == InputType.Password)
            txtResponse.Visibility = Visibility.Collapsed;
        else
            txtPasswordResponse.Visibility = Visibility.Collapsed;
    }

    void PromptDialog_Loaded(object sender, RoutedEventArgs e)
    {
        if (_inputType == InputType.Password)
            txtPasswordResponse.Focus();
        else
            txtResponse.Focus();
    }

    public static string Prompt(string question, string title, string defaultValue = "", InputType inputType = InputType.Text)
    {
        PromptDialog inst = new PromptDialog(question, title, defaultValue, inputType);
        inst.ShowDialog();
        if (inst.DialogResult == true)
            return inst.ResponseText;
        return null;
    }

    public string ResponseText
    {
        get
        {
            if (_inputType == InputType.Password)
                return txtPasswordResponse.Password;
            else
                return txtResponse.Text;
        }
    }

    private void btnOk_Click(object sender, RoutedEventArgs e)
    {
        DialogResult = true;
        Close();
    }

    private void btnCancel_Click(object sender, RoutedEventArgs e)
    {
        Close();
    }
}

So you can call it like:

所以你可以这样称呼它:

string repeatPassword = PromptDialog.Prompt("Repeat password", "Password confirm", inputType: PromptDialog.InputType.Password);

回答by xtds

Great answer of Josh, all credit to him, I slightly modified it to this however:

乔希的好回答,全归功于他,但是我稍微修改了一下:

MyDialog Xaml

我的对话框 Xaml

    <StackPanel Margin="5,5,5,5">
        <TextBlock Name="TitleTextBox" Margin="0,0,0,10" />
        <TextBox Name="InputTextBox" Padding="3,3,3,3" />
        <Grid Margin="0,10,0,0">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <Button Name="BtnOk" Content="OK" Grid.Column="0" Margin="0,0,5,0" Padding="8" Click="BtnOk_Click" />
            <Button Name="BtnCancel" Content="Cancel" Grid.Column="1" Margin="5,0,0,0" Padding="8" Click="BtnCancel_Click" />
        </Grid>
    </StackPanel>

MyDialog Code Behind

MyDialog 背后的代码

    public MyDialog()
    {
        InitializeComponent();
    }

    public MyDialog(string title,string input)
    {
        InitializeComponent();
        TitleText = title;
        InputText = input;
    }

    public string TitleText
    {
        get { return TitleTextBox.Text; }
        set { TitleTextBox.Text = value; }
    }

    public string InputText
    {
        get { return InputTextBox.Text; }
        set { InputTextBox.Text = value; }
    }

    public bool Canceled { get; set; }

    private void BtnCancel_Click(object sender, System.Windows.RoutedEventArgs e)
    {
        Canceled = true;
        Close();
    }

    private void BtnOk_Click(object sender, System.Windows.RoutedEventArgs e)
    {
        Canceled = false;
        Close();
    }

And call it somewhere else

并在别处调用它

var dialog = new MyDialog("test", "hello");
dialog.Show();
dialog.Closing += (sender,e) =>
{
    var d = sender as MyDialog;
    if(!d.Canceled)
        MessageBox.Show(d.InputText);
}

回答by vapcguy

You don't need ANYof these other fancy answers. Below is a simplistic example that doesn't have all the Margin, Height, Widthproperties set in the XAML, but should be enough to show how to get this done at a basic level.

您不需要任何其他花哨的答案。下面是一个简单的示例,它没有在 XAML 中设置所有Margin, Height,Width属性,但应该足以说明如何在基本级别完成此操作。

XAML
Build a Windowpage like you would normally and add your fields to it, say a Labeland TextBoxcontrol inside a StackPanel:

XAML像往常一样
构建Window页面并向其中添加字段,例如 aLabel和a 中的TextBox控件StackPanel

<StackPanel Orientation="Horizontal">
    <Label Name="lblUser" Content="User Name:" />
    <TextBox Name="txtUser" />
</StackPanel>

Then create a standard Buttonfor Submission ("OK" or "Submit") and a "Cancel" button if you like:

然后创建Button提交标准(“确定”或“提交”)和“取消”按钮(如果您愿意):

<StackPanel Orientation="Horizontal">
    <Button Name="btnSubmit" Click="btnSubmit_Click" Content="Submit" />
    <Button Name="btnCancel" Click="btnCancel_Click" Content="Cancel" />
</StackPanel>

Code-Behind
You'll add the Clickevent handler functions in the code-behind, but when you go there, first, declare a public variable where you will store your textbox value:

代码隐藏
您将Click在代码隐藏中添加事件处理函数,但是当您去那里时,首先声明一个公共变量,您将在其中存储文本框值:

public static string strUserName = String.Empty;

Then, for the event handler functions (right-click the Clickfunction on the button XAML, select "Go To Definition", it will create it for you), you need a check to see if your box is empty. You store it in your variable if it is not, and close your window:

然后,对于事件处理函数(右键单击ClickXAML 按钮上的函数,选择“转到定义”,它将为您创建它),您需要检查您的框是否为空。如果不是,则将其存储在变量中,然后关闭窗口:

private void btnSubmit_Click(object sender, RoutedEventArgs e)
{        
    if (!String.IsNullOrEmpty(txtUser.Text))
    {
        strUserName = txtUser.Text;
        this.Close();
    }
    else
        MessageBox.Show("Must provide a user name in the textbox.");
}

Calling It From Another Page
You're thinking, if I close my window with that this.Close()up there, my value is gone, right? NO!!I found this out from another site: http://www.dreamincode.net/forums/topic/359208-wpf-how-to-make-simple-popup-window-for-input/

从另一个页面调用它
你在想,如果我关闭我的窗口this.Close(),我的价值就消失了,对吧? 不!!我从另一个站点发现了这一点:http: //www.dreamincode.net/forums/topic/359208-wpf-how-to-make-simple-popup-window-for-input/

They had a similar example to this (I cleaned it up a bit) of how to open your Windowfrom another and retrieve the values:

他们有一个与此类似的示例(我清理了一下)如何Window从另一个打开您的并检索值:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void btnOpenPopup_Click(object sender, RoutedEventArgs e)
    {
        MyPopupWindow popup = new MyPopupWindow();  // this is the class of your other page

        //ShowDialog means you can't focus the parent window, only the popup
        popup.ShowDialog(); //execution will block here in this method until the popup closes

        string result = popup.strUserName;
        UserNameTextBlock.Text = result;  // should show what was input on the other page
    }
}

Cancel Button
You're thinking, well what about that Cancel button, though? So we just add another public variable back in our pop-up window code-behind:

取消按钮
你在想,那个取消按钮怎么样?所以我们只需在我们的弹出窗口代码隐藏中添加另一个公共变量:

public static bool cancelled = false;

And let's include our btnCancel_Clickevent handler, and make one change to btnSubmit_Click:

让我们包括我们的btnCancel_Click事件处理程序,并对以下内容进行更改btnSubmit_Click

private void btnCancel_Click(object sender, RoutedEventArgs e)
{        
    cancelled = true;
    strUserName = String.Empty;
    this.Close();
}

private void btnSubmit_Click(object sender, RoutedEventArgs e)
{        
    if (!String.IsNullOrEmpty(txtUser.Text))
    {
        strUserName = txtUser.Text;
        cancelled = false;  // <-- I add this in here, just in case
        this.Close();
    }
    else
        MessageBox.Show("Must provide a user name in the textbox.");
}

And then we just read that variable in our MainWindowbtnOpenPopup_Clickevent:

然后我们只是在我们的MainWindowbtnOpenPopup_Click事件中读取该变量:

private void btnOpenPopup_Click(object sender, RoutedEventArgs e)
{
    MyPopupWindow popup = new MyPopupWindow();  // this is the class of your other page
    //ShowDialog means you can't focus the parent window, only the popup
    popup.ShowDialog(); //execution will block here in this method until the popup closes

    // **Here we find out if we cancelled or not**
    if (popup.cancelled == true)
        return;
    else
    {
        string result = popup.strUserName;
        UserNameTextBlock.Text = result;  // should show what was input on the other page
    }
}

Long response, but I wanted to show how easy this is using public staticvariables. No DialogResult, no returning values, nothing. Just open the window, store your values with the button events in the pop-up window, then retrieve them afterwards in the main window function.

回复很长,但我想展示使用public static变量是多么容易。不DialogResult,没有返回值,什么都没有。只需打开窗口,在弹出窗口中使用按钮事件存储您的值,然后在主窗口函数中检索它们。