1

I'm creating a dynamic dialog box in xamarin.android and I want the dialog box to receive a function that it will execute upon clicking the action button.

Heres my code:

public static void ShowDialogBox(Context context, Function dynamicFunction)
{
    Dialog popupDialog = new Dialog(context);
    popupDialog.SetContentView(Resource.Layout.dialog_dynamic);
    popupDialog.Window.SetSoftInputMode(SoftInput.AdjustResize);
    popupDialog.Window.SetBackgroundDrawableResource(Android.Resource.Color.Transparent);
    popupDialog.Show();

    TextView title = popupDialog.FindViewById<TextView>(Resource.Id.dialog_title);
    TextView content = popupDialog.FindViewById<TextView>(Resource.Id.dialog_content);
    ImageView icon = popupDialog.FindViewById<ImageView>(Resource.Id.dialog_icon);
    Button actionButton = popupDialog.FindViewById<Button>(Resource.Id.dialog_action_button);

    popupDialog.FindViewById<ImageButton>(Resource.Id.dialog_close).Click += delegate { popupDialog.Dismiss(); };
    popupDialog.FindViewById<Button>(Resource.Id.dialog_cancel_button).Click += delegate { popupDialog.Dismiss(); };
    
    actionButton.Click += dynamicFunction;
}

*Take note that the Function parameter is just an example. Also I will make the text and content in this dialog box a parameter.

Example scenario:

  1. If I send GetCurrentDate function to this dialog box, when the action button is clicked it will get the current date.
  2. If I send OpenBluetooth function to this dialog box, when the action button is clicked it will open the Bluetooth

It is possible to send another function to this ShowDialogBox function and run it when the action button is clicked? My purpose here it to make my code clean and easy to use.

Palle Due
  • 5,929
  • 4
  • 17
  • 32
Elohist
  • 83
  • 1
  • 11
  • 1
    Have you already looked into using Delegates? You can use a delegate as a parameter and this will basically be the function to execute dynamically. Here is a question already answered with the same requirement as your question. https://stackoverflow.com/questions/2082615/pass-method-as-parameter-using-c-sharp – Nico May 05 '22 at 09:56
  • 1
    from my experience, a shared dialog (or form) is a dead-end road. I mean that the cost of the business layer/UI to be able to adapt to many (different) situations and the cost of creating several components is 99% of times in favor of the latter. If you want, you may gain some advantage with a clever composition-pattern, but -again- not worth it if the dialogs are pretty simple. – Mario Vernari May 05 '22 at 10:01

3 Answers3

2

As @Nico already commented, you can use Func or a delegate as a parameter. I'd suggest you use Action instead.

The Clicked event on Xamarin.Forms.Button uses an event handler with the signature void OnClicked(object? sender, EventArgs e). Therefore, your signature would use a Action<object?, EventArgs> parameter.

A couple things to note:

  • If you don't use nullable reference types in your project, omit the question marks
  • You need to check the parameter for null before assigning it to the Clicked event
  • Invoking an Action does not return anything. If you want to "get the current date", your action must write the current date in a field or control
  • If your function needs other parameters, you need to pass a delegate (or wrap your function call in a function with the sender and e parameters: ShowDialogBox(context, (sender, e) => MyFunction("other data"))
G_hi3
  • 588
  • 5
  • 22
1

Object orientation can help you: you can abstract your function into a class and then derive any specilized function class to implement your specific action. Something like the following:

abstract class ActionClassBase
{
    public abstract void Action();

    private string data = "";
    public string Data { get { return data; } set { data = value; } }
}

class GetCurrentDateAction : ActionClassBase
{
    public override void Action()
    {
        Data = DateTime.Now.ToString();
    }
}

class OpenBlueToothAction : ActionClassBase
{
    public override void Action()
    {
        Data = "BlueTooth opened";
    }
}


public static void ShowDialogBox(Context context, ActionClassBase action)
{
    Dialog popupDialog = new Dialog(context);
    popupDialog.SetContentView(Resource.Layout.dialog_dynamic);
    popupDialog.Window.SetSoftInputMode(SoftInput.AdjustResize);
    popupDialog.Window.SetBackgroundDrawableResource(Android.Resource.Color.Transparent);
    popupDialog.Show();

    TextView title = popupDialog.FindViewById<TextView>(Resource.Id.dialog_title);
    TextView content = popupDialog.FindViewById<TextView>(Resource.Id.dialog_content);
    ImageView icon = popupDialog.FindViewById<ImageView>(Resource.Id.dialog_icon);
    Button actionButton = popupDialog.FindViewById<Button>(Resource.Id.dialog_action_button);

    popupDialog.FindViewById<ImageButton>(Resource.Id.dialog_close).Click += delegate { popupDialog.Dismiss(); };
    popupDialog.FindViewById<Button>(Resource.Id.dialog_cancel_button).Click += delegate { popupDialog.Dismiss(); };

    actionButton.Click += (sender, ev) => action.Action();
}

Further with this approach it's very easy to add new functions: just derive a new class and override the Action() method

Marco Beninca
  • 605
  • 4
  • 15
  • Another question is how can I close the dialog box using the `action.Action()`? – Elohist May 06 '22 at 00:54
  • Why do you want to using `action.Action()` to close the dialog box? There is already a cancel_button in your code. In addition, closing the dialog box need to call the `Dismiss()` method. So if you want to close it with the `action.Action()`, you need to make ActionClassBase get the instance of the dialog and then call the `Dismiss()` method. @Elohist – Liyun Zhang - MSFT May 06 '22 at 01:57
  • I want to close it after execution of the `action.Action()`. How can I pass the my dialog box in `ActionClassBase`? – Elohist May 06 '22 at 02:21
  • You can try the code in my answer.@Elohist – Liyun Zhang - MSFT May 06 '22 at 02:38
  • @Elohist just add a reference to `Window` and a bool flag to decide to close or not to the base class (set them inside the `ShowDialogBox` method). Then on each `Action` you can decide to close the dialog or not – Marco Beninca May 06 '22 at 06:29
1

You can create a Dialog in the ActionClassBase and call the Dismiss() method in the Action(). Such as

abstract class ActionClassBase
{
  public  Dialog popupDialog;
  public abstract void Action();

  private string data = "";
  public string Data { get { return data; } set { data = value; } }
  }

class GetCurrentDateAction : ActionClassBase
{
  public override void Action()
  {
    Data = DateTime.Now.ToString();
    base.popupDialog.Dismiss();
  }
}

class OpenBlueToothAction : ActionClassBase
{
  public override void Action()
  {
    Data = "BlueTooth opened";
    base.popupDialog.Dismiss();
  }
}

And then, pass the dialog to the ActionClassBase in the ShowDialogBox(Context context, Function dynamicFunction) . Such as:

Dialog popupDialog = new Dialog(context);
popupDialog.SetContentView(Resource.Layout.dialog_dynamic);
popupDialog.Window.SetSoftInputMode(SoftInput.AdjustResize);
popupDialog.Window.SetBackgroundDrawableResource(Android.Resource.Color.Transparent);
dynamicFunction.popupDialog = popupDialog;
Liyun Zhang - MSFT
  • 8,271
  • 1
  • 2
  • 14