Is there a Form.Showdialog equivalent for Gtk# Win

2019-05-29 01:48发布

Using Windows Forms or WPF I can open a dialog window by calling ShowDialog. How can I do that using Gtk#?

I tried just making the Window modal, but although it prevents the user from interacting with the calling window it does not wait for the user to close the dialog before running the code after ShowAll().

标签: dialog gtk#
3条回答
贪生不怕死
2楼-- · 2019-05-29 02:12

I implemented the following method on my Gtk.Dialog:

public ResponseType ShowDialog()
{
  List<ResponseType> responseTypes = new List<ResponseType>
  {
    // list all the ResponseTypes that you have buttons for
    // or that you call this.Respond(...) with
    ResponseType.Ok,
    ResponseType.Cancel
  };

  this.Modal = true;

  // start with any ResponseType that isn't contained in responseTypes
  ResponseType response = ResponseType.None;

  while (!responseTypes.Contains(response))
  {
    response = (ResponseType)this.Run();
  }
  this.Destroy();
  return response;
}
查看更多
一纸荒年 Trace。
3楼-- · 2019-05-29 02:20

I'm trying to create a more complex dialog, one that doesn't have windows - it's a search dialog with a completion treeview nested in a scrollview, and is closed with Enter or Escape.

Here's how I've figured you put together the mechanics of a modal dialog manually:

  • Define a property on your dialog that indicates whether it is completed or not. I'm calling mine ModalResult, an enum with values None, OK and Cancel.

  • Ensure you have the parent window of the dialog handy (dialogParent below)

Sample code:

// assuming Dispose properly written per @mhutch
using (window = new MyDialogWindow()) 
{
    window.TransientFor = dialogParent;
    window.Modal = true;
    window.Show();
    while (window.ModalResult == ModalResult.None)
        Application.RunIteration(true);
    // now switch on value of modal result
 }

Note however this Ubuntu bug with overlay scrollbars. I don't use them and my app is for personal use, but YMMV.

查看更多
啃猪蹄的小仙女
4楼-- · 2019-05-29 02:22

Instead of using a Gtk.Window, use Gtk.Dialog, then call dialog.Run (). This returns an integer value corresponding to the ID of the button the user used to close the dialog.

e.g.

Dialog dialog = null;
ResponseType response = ResponseType.None;

try {
    dialog = new Dialog (
        "Dialog Title",
        parentWindow,
        DialogFlags.DestroyWithParent | DialogFlags.Modal,
        "Overwrite file", ResponseType.Yes,
       "Cancel", ResponseType.No
    );
    dialog.VBox.Add (new Label ("Dialog contents"));
    dialog.ShowAll ();

    response = (ResponseType) dialog.Run ();
} finally {
    if (dialog != null)
        dialog.Destroy ();
}

if (response == ResponseType.Yes)
    OverwriteFile ();

Note that Dispose()ing a widget in GTK# doesn't Destroy() it in GTK# -- a historical design accident, preserved for backwards-compatibility. However, if you use a custom dialog subclass you can override Dispose to also Destroy the dialog. If you also add the child widgets and the ShowAll() call in the constructor, you can write nicer code like this:

ResponseType response = ResponseType.None;
using (var dlg = new YesNoDialog ("Title", "Question", "Yes Button", "No Button"))
    response = (ResponseType) dialog.Run ();

if (response == ResponseType.Yes)
        OverwriteFile ();

Of course, you could take it a step further and write an equivalent of ShowDialog.

查看更多
登录 后发表回答