MessageBox — useful window for different GUI frameworks, but you can't find it in AvaloniaUI.
Let's try to do it.


Solution, which I wanna improve and support, you can find on nuget and on gitlab. It'll be glad, if somebody bring new ideas with his/her pull requests.

I wanna create my lib as easy and useful as WPF's messagebox is.

Let's start


Call this method:

MessageBox.ShowForResult("test","Wanna test smth?",MessageBox.MessageBoxButtons.OkCancel);

and get window with header, content(text) and two buttons. (Windows 10, Ubuntu 18.04)



Class MessageBox contains public 4 methods:
ShowForResult — return result of button's click.
ShowDialog — return result of button's click and set this window as dialog window for chosen parent.
Show — show window with one «ok» button, which ignore result of click (return void).
ShowNative — try to call native window for platform, if failed, call ShowForResult.
API

How it works:


In every method create window,

var messageBox = new MessageBox();

and set content for each.

 messageBox.Content = CreateBaseMsgBox(text, buttons, messageBox);

Content is a grid, which include rows, one for textbox:

 var textBlock = new TextBlock();
 textBlock.Text = text;
 textBlock.TextAlignment = TextAlignment.Center;
 textBlock.TextWrapping = TextWrapping.Wrap;
 Grid.SetRow(textBlock,0);
 grid.Children.Add(textBlock);

other for grid with buttons:

var btnGrid = GetButtonGrid(GetButton(window, MessageBoxResult.Yes),
 GetButton(window,MessageBoxResult.No));
 Grid.SetRow(btnGrid,1);
 grid.Children.Add(btnGrid);

Full listing for GetButtonGrid.
private static Grid GetButtonGrid(params Button[] buttons)
        {
            var grid = new Grid();
            List<ColumnDefinition> definitions = new List<ColumnDefinition>();
            for (int i = 0; i < buttons.Length; i++)
            {
                definitions.Add(new ColumnDefinition{Width = new GridLength(5)});
                definitions.Add(new ColumnDefinition{Width = new GridLength(1,GridUnitType.Star)});
            }
            definitions.Add(new ColumnDefinition{Width = new GridLength(5)});
            grid.ColumnDefinitions.AddRange(definitions);
             var j = 1;
            foreach (var btn in buttons)
            {
                Grid.SetColumn(btn,j);
                j += 2;
                grid.Children.Add(btn);
            }
            return grid;
        }



The functionality of the buttons is given by the method:

GetButton(MessageBox window,MessageBoxResult result)

Read more
private static Button GetButton(MessageBox window,MessageBoxResult result)
        {
           var btn = new Button();
           btn.Content = result.ToString();
           btn.Click += (_, __) =>
           {
               window.Res = result;
               window.Close();
           };
           return btn;
        }


The method accepts a window which be manipulated by buttons, and result returned by them.

And, the last thing to consider is a code fragment that provides the result of a button click:

var tcs = new TaskCompletionSource<MessageBoxResult>();
messageBox.Closed += delegate { tcs.TrySetResult(messageBox.Res); };
...
return tcs.Task;

As a result, we get simple windows with buttons, which will allow us to create cross-platform MessageBox.

Grateful for user worldbeater.

Комментарии (7)


  1. FoggyFinder
    02.06.2019 10:35

    First of all — nice work!


    There is also another package for MessageBox — StarDebris.Avalonia.MessageBox:


    NuGet
    Gitlab


    Although this one is a bit outdated. I thought to use it in my personal project but after all I've rejected to go this way and wrote code that fitted my requirement by myself.


    If you don't mind I ask some questions:


    1. Why have you avoided of using xaml?
    2. Why is repo on gitlab? (Github is much, much more popular)
    3. Somewhere code is really looks odd, for example:

    var messageBox = CreateWindow(title, text, buttons, windowSize, bitmap);
    var tcs = new TaskCompletionSource<MessageBoxResult>();
    messageBox.Title = title;
    messageBox.WindowStartupLocation = WindowStartupLocation.CenterScreen;
    messageBox.Closed += delegate { tcs.TrySetResult(messageBox.Res); };

    definitely not cleanest API.
    You pass title to the CreateWindow but ignore this parameter at all there. And so on.


    1. Larymar Автор
      02.06.2019 11:06

      Thanks
      1) about xaml, it was my research and i never create nuget package before. Now I wanna (in proccees) rebuild (redisine) all with using styles, xaml, and users controls
      2) I start working with gitlab, because some years ago githab has no private repos, okey mb i move here
      3) about api, ty, i'll improve article


      1. FoggyFinder
        02.06.2019 11:58

        1) about xaml, it was my research and i never create nuget package before.

        To be honest I don't see how it's related. Good luck, anyway.
        Although if you interested in additional research I suggest you try to implement it with F#.


        1. Larymar Автор
          02.06.2019 14:28

          yet, some hours ago i read ur article, so cool, like it, but hadn't enough carma to like it)


  1. KvanTTT
    02.06.2019 13:52


    It seems to me that the Windows Message box contains excess buttons minimize and maximize. Is it possible to get rid of them?


    1. Larymar Автор
      02.06.2019 14:30

      I think only in future updates, couse i can't do it by avalonia and need to call win api, as real it's strange: in Linux i haven't max button, but in win that's one


  1. KvanTTT
    04.06.2019 15:57

    I've developed the similar control inside another project, but maybe your code is better and has more features.