Customize Buttons?

Hello Team Syncfusion,

I am looking into the SfPopup control, and wonder if there is any way to customize the buttons used for the popup?

Thank you for any assistance you can provide.


20 Replies 1 reply marked as answer

MI Mike-E June 20, 2025 04:53 PM UTC

Looks like there is the PopupStyle property:

Snippet
<popup:SfPopup.PopupStyle>
        <popup:PopupStyle FooterBackground="#211f33" MessageBackground="#211f33" HeaderBackground="#211f33"
                          HeaderTextColor="White"
                          MessageFontFamily="Primary" MessageTextColor="White" MessageFontSize="20"
                          AcceptButtonBackground="#6666ff"
                          AcceptButtonTextColor="White"
                          FooterButtonCornerRadius="5" />
    </popup:SfPopup.PopupStyle>

Additionally, Grok seems to imply a footer template can be used:

                <sfPopup:SfPopup.FooterTemplate>
                    <DataTemplate>
                        <Grid ColumnDefinitions="Auto,Auto"
                              HorizontalOptions="Center"
                              VerticalOptions="Center"
                              ColumnSpacing="12">
                            <Button Text="Cancel"
                                    Grid.Column="0"
                                    WidthRequest="120"
                                    HeightRequest="40"
                                    BackgroundColor="Red"
                                    TextColor="White"
                                    CornerRadius="10"
                                    Command="{Binding Source={x:Reference sfPopup}, Path=BindingContext.DeclineCommand}"
                                    CommandParameter="{x:Reference sfPopup}" />
                            <Button Text="Confirm"
                                    Grid.Column="1"
                                    WidthRequest="120"
                                    HeightRequest="40"
                                    BackgroundColor="Green"
                                    TextColor="White"
                                    CornerRadius="10"
                                    Command="{Binding Source={x:Reference sfPopup}, Path=BindingContext.AcceptCommand}"
                                    CommandParameter="{x:Reference sfPopup}" />
                        </Grid>
                    </DataTemplate>
                </sfPopup:SfPopup.FooterTemplate>

However, when I tried this, I could not get the BindingContext.AcceptCommand to resolve. 🤔



MI Mike-E June 20, 2025 06:36 PM UTC

Additionally, it would be ideal for us to:

  1. Open the Popup so that it is aligned centered bottom of the screen. 
  2. Move the close button the left
  3. Stretch the OneButton in the footer so it's 100% width

Is this possible?



RM RiyasHameed MohamedAbdulKhader Syncfusion Team June 23, 2025 02:02 PM UTC

Hi Mike-E,

We have reviewed your reported queries and provided solutions below:

Query 1: Popup positioning at the center bottom of the screen

To position the popup at the center bottom of the screen, you can use the Show(x, y) method. By subtracting the popup height from the device screen height, you can position the popup appropriately. Please refer to the code snippet below:

var height = DeviceDisplay.MainDisplayInfo.Height / DeviceDisplay.MainDisplayInfo.Density;

var width = DeviceDisplay.MainDisplayInfo.Width / DeviceDisplay.MainDisplayInfo.Density;

var popupX = (width - popup.WidthRequest) / 2;

var popupY = height - popup.HeightRequest;

popup.Show(popupX, popupY);

Query 2: Positioning the close button to the left

Currently, SfPopup does not provide built-in support to position the close button to the left. However, you can achieve this by using the HeaderTemplate and implementing an image with a close icon aligned to the left. For your reference, please see the sample and user guide below:

Layout Customizations in .NET MAUI Popup control | Syncfusion

Query 3: Layout Footer button with 100% width

The default accept button width in the popup cannot be changed directly. To achieve a layout where the button spans the full width of the popup, use the FooterTemplate and define the button with a width matching PopupView. Please refer to the user guide:

Layout Customizations in .NET MAUI Popup control | Syncfusion

Query 4: AcceptCommand is not invoked

We tested the scenario using your provided code snippet and binding. The AcceptCommand is invoked as expected. We have attached a sample for your reference.

Regards,

Riyas Hameed M


Attachment: SfPopupSample_5831460.zip


MI Mike-E June 24, 2025 03:04 PM UTC

Hi Riyas,


Thank you very much for your reply and sample.  They are both greatly appreciated.  

For the Positioning, please be aware we are using `AutoSizeMode="Height"` but both the Height/Width (and requests) return -1.  Is there a way to get the actual width/height of the control without using Width/Height/Request ?


For the AcceptCommand issue, it appears you are using SfPopup.Show whereas we are using SfPopup.ShowAsync.  Can you please confirm on your side the AcceptCommand does not work when using ShowAsync.  If you have any further guidance around this, it would be appreciated.


Thank you again for your excellent support.



MI Mike-E June 24, 2025 03:14 PM UTC

Oh, I'd also like to thank you for the close-button sample code and providing that solution as well.  That seems to address that question. 👍



RM RiyasHameed MohamedAbdulKhader Syncfusion Team June 25, 2025 02:11 PM UTC

Mike-E,

We have reviewed your query and would like to inform you that calculating the center position of the popup requires obtaining its width. However, with our implementation of AutoSizeMode, the popup’s width and height are determined when the popup opens. Therefore, it’s not feasible to get these dimensions before the popup is displayed.

As a workaround to display the popup at the bottom, we recommend setting AutoSizeMode to height and specifying a fixed width for the popup. This is because the width cannot be retrieved prior to the popup being displayed. Additionally, set the Y position to the page height, enabling the popup to appear at the bottom of the screen. the Y position of the popup will automatically be adjusted if it exceeds the screen height.

Regarding the AcceptCommand, we confirm that when using the ShowAsync method, the command is invoked as expected. Please confirm whether the issue lies in the incorrect result or if the AcceptCommand is not being triggered. If possible, modify the attached sample to reproduce the problem on our end, as this will assist us in validating the issue.

Attachment: SfPopupSample_(2)_84310a3e.zip


MI Mike-E June 27, 2025 03:44 PM UTC

Hi RiyasHameed,

Thank you again for your amazing support, complete with great code to demonstrate your guidance.  I really appreciate it.  Yes, I see now that you have an accept command and it gets called in the model.  I did not see this before.

What I was doing was pressing Accept, and expecting it to close and return the boolean from ShowAsync.  That is, there's a default command for the Popup that doesn't require the model, and I want to use that when I customize the footer and refer to it instead.  Stated another way,  I do not want to create and define a command, but simply refer to the one that already exists by default for the SfPopup (it closes the popup and returns true).   Does that make sense?

If you can provide further guidance on how to do this, that would be appreciated.

As for the display, I greatly appreciate your assistance there as well.  It would of course be ideal to have automatic calculations based on the width + height of the control and to align it accordingly.  However, since this is v1 a little math will do the trick here.

Thank you for your continued assistance.



AP Abinesh Palanisamy Syncfusion Team June 30, 2025 12:33 PM UTC

Hi Mike-E,
 

On your end, you were using the FooterTemplate to display the Accept and Cancel buttons. When the FooterTemplate is used to customize the popup footer with custom buttons, the built-in Accept and Cancel functionality of the SfPopup is overridden—this is expected behavior.
All actions triggered by the custom buttons within the FooterTemplate need to be handled manually in your implementation. Accordingly, in the previously shared sample, we used commands in the ViewModel to define the actions of the Accept and Cancel buttons.
If you have any further questions, we’re happy to help!.

 
Regards,
Abinesh P


MI Mike-E June 30, 2025 04:15 PM UTC

Hi Abinesh, thank you for your reply, it is appreciated.  I do understand that the default functionality is overridden, but I also want to access the previous/default behavior.  Is there a way to do this?  This is what is precluding us from overriding the FooterTemplate at the moment.  Thank you for any further assistance you can provide.



AP Abinesh Palanisamy Syncfusion Team July 1, 2025 01:31 PM UTC

Hi Mike-E,
 

To address the reported scenario, we have implemented a workaround that replicates the functionality of the built-in ShowAsync() method of SfPopup, with custom FooterTemplate buttons. We used TaskCompletionSource<bool> to detect the result, creating a bridge between user interactions and asynchronous code flow.


Task<bool> property represents an operation that will be completed in the future. When a button is clicked, _currentTask.SetResult(true) is called for the Accept button, and _currentTask.SetResult(false) for the Cancel button. This completes the task with the appropriate value and allows the calling code to continue execution based on the result.


Code snippets :


private async void Button_Clicked(object sender, EventArgs e)

{

    bool result = await ShowPopupAsync();

    if (result)

    {

        await DisplayAlert("Result", "Accepted", "OK");

    }

    else

    {

        await DisplayAlert("Result", "Canceled", "OK");

    }

}

 

public async Task<bool> ShowPopupAsync()

{

    var viewModel = (PopupViewModel)BindingContext;

    var tcs = new TaskCompletionSource<bool>();

 

    viewModel.SetCurrentTask(tcs);

 

    sfPopup.Show();

 

    return await tcs.Task;

}


public void SetCurrentTask(TaskCompletionSource<bool> tcs)

  {

      _currentTask = tcs;

  }


 

private void OnDeclineClicked(SfPopup popup)

{

    popup.IsOpen = false;

    _currentTask?.SetResult(false);

}

 

private void OnAcceptClicked(SfPopup popup)

{

    popup.IsOpen = false;

    _currentTask?.SetResult(true);

}


We have included a sample for your reference. If you have any further questions, we’re happy to help.


Regards,

Abinesh P


Attachment: SfPopupSample_19e1c080.zip


MI Mike-E July 1, 2025 02:39 PM UTC

Hi Abinesh,

Thank you very much for taking the time to provide the custom code.  I greatly appreciate your time and willingness to help.  While the code is sufficient, I was hoping that the default behavior was exposed in some way that I can simply reference it, rather than having to add more code to my solution.  I will use your guidance for now, but I ask that you please consider exposing the default behavior in some way so that users who simply want to customize their footer while leaving the default behavior intact can do so.

Intuitively, it would seem that both the AcceptCommand and RejectCommand would be set to these default implementations, and then all one has to do is bind to these commands in the FooterTemplate and have the same default behavior as before the footer was overridden.

Thank you again for your assistance, and for any consideration toward making this a feature request for a future version of your impressive control suite. 🙏



AP Abinesh Palanisamy Syncfusion Team July 2, 2025 12:13 PM UTC

Hi Mike-E,

We have carefully reviewed the source code and, unfortunately, exposing the concept of returning a result (such as the ShowAsync feature) is not feasible as it relies on built-in footer button actions. We recommend utilizing the workaround mentioned in our previous update. Please feel free to reach out if you have any further questions. We are here to assist you.
Regards,
Abinesh P



MI Mike-E July 3, 2025 05:00 PM UTC

Hi Abinesh, thank you for your reply.


We have carefully reviewed the source code and, unfortunately, exposing the concept of returning a result (such as the ShowAsync feature) is not feasible as it relies on built-in footer button actions

Please pardon the confusion, but the request is not to expose the return of a result, and has nothing to do with ShowAsync.  The request is to expose the default commands used by the SfPopUp control so that the user can easily bind to it in the FooterTemplate when they override the footer template, and do not have to create their own implementations.

As the AcceptCommand is null by default, the request is to make it so the AcceptCommand is assigned to this default command, so that the user can access it from the FooterTemplate through a simple binding.  The same goes for the DeclineCommand  This will save the user from having to create more code, and therefore offer a better experience for those who wish to extend your controls.

Thank you for your consideration. 🙏



AP Abinesh Palanisamy Syncfusion Team July 4, 2025 10:05 AM UTC

Hi Mike-E,

When using customized buttons in the footer, it is not possible to recognize the button clicks at the source level or execute the built-in commands directly. Therefore, it is not feasible to provide support for this behavior.
However, if you need to perform actions using the AcceptCommand and DeclineCommand when the Accept and Decline buttons are clicked, you can achieve this by binding these commands to your custom buttons. This will ensure the commands are triggered when the respective buttons are tapped, allowing you to handle the command execution as needed.
In the sample we previously shared, we demonstrated a similar approach to perform actions using commands. Please refer to that sample and code snippets for more details.

Code snippet:
 
 <DataTemplate>
     <Grid ColumnDefinitions="Auto,Auto"
           HorizontalOptions="Center"
           VerticalOptions="Center"
           ColumnSpacing="12">
         <Button Text="Cancel"
                 Grid.Column="0"
                 WidthRequest="120"
                 HeightRequest="40"
                 BackgroundColor="Red"
                 TextColor="White"
                 CornerRadius="10"
                 Command="{Binding Source={x:Reference sfPopup}, Path=BindingContext.DeclineCommand}"
                 CommandParameter="{x:Reference sfPopup}" />
         <Button Text="Confirm"
                 Grid.Column="1"
                 WidthRequest="120"
                 HeightRequest="40"
                 BackgroundColor="Green"
                 TextColor="White"
                 CornerRadius="10"
                 Command="{Binding Source={x:Reference sfPopup}, Path=BindingContext.AcceptCommand}"
                 CommandParameter="{x:Reference sfPopup}" />
     </Grid>
 </DataTemplate>

 
Regards,
Abinesh P


MI Mike-E July 8, 2025 04:09 PM UTC

Hi Abinesh,

Yes! That is exactly what I am thinking and have in mind.  It would seem that if I override the FooterTemplate, do not assign the AcceptCommand, and provide the following binding:

Command="{Binding Source={x:Reference sfPopup}, Path=BindingContext.AcceptCommand}"

That this would utilize the default behavior (close and return true) without any custom code on my part.  Make sense?

Thank you for your continued consideration.



MI Mike-E July 8, 2025 04:09 PM UTC

Hi Abinesh,

Yes! That is exactly what I am thinking and have in mind.  It would seem that if I override the FooterTemplate, do not assign the AcceptCommand, and provide the following binding:

Command="{Binding Source={x:Reference sfPopup}, Path=BindingContext.AcceptCommand}"

That this would utilize the default behavior (close and return true) without any custom code on my part.  Make sense?

Thank you for your continued consideration.



AP Abinesh Palanisamy Syncfusion Team July 9, 2025 10:48 AM UTC

Hi Mike-E,


Unfortunately, it's not possible to access the default command implementations through bindings when using a custom footer template. When you override the FooterTemplate, the internal command logic that handles the default behavior (closing and returning true/false) is not exposed in a way that can be directly bound to custom buttons. The default behavior is designed to work specifically with the default button configuration and unfortunately isn't available as separate commands that could be referenced in custom implementations
 

When customizing the FooterTemplate, all actions triggered by the custom buttons need to be handled manually in your implementation. 


We appreciate your understanding, and if you have any further questions or need assistance with the current implementation, we’re happy to help.
 

Regards,

Abinesh P


Marked as answer

MI Mike-E July 9, 2025 01:07 PM UTC

Thank you, Abinesh, for your thoughtful and detailed response.  I greatly appreciate you walking through this scenario and making sure your customer is heard.  I continue to admire and appreciate your excellent support.  Have a great day out there.



AP Abinesh Palanisamy Syncfusion Team July 10, 2025 05:45 AM UTC

Hi Mike-E,

We’re truly glad to hear that you found the response helpful! It's always a pleasure to provide support that meets your needs. Thank you for your kind feedback, and please don't hesitate to reach out if you need any further assistance.
Regards,
Abinesh P


JM John Miller June 1, 2026 04:28 AM UTC

For anyone landing here later, the cleanest way to keep ShowAsync-style behavior with a custom FooterTemplate is to wrap the TaskCompletionSource pattern in an extension method, so you write it once and forget about it.

public static class SfPopupExtensions

{

    public static Task<bool> ShowAsyncCustom(this SfPopup popup)

    {

        var tcs = new TaskCompletionSource<bool>();


        EventHandler<CancelEventArgs> closingHandler = null;

        closingHandler = (s, e) =>

        {

            popup.Closing -= closingHandler;

            // Fallback: backdrop tap / back button

            tcs.TrySetResult(false);

        };

        popup.Closing += closingHandler;


        popup.Show();

        return tcs.Task;

    }


    public static void Accept(this SfPopup popup)

    {

        popup.BindingContext = new { Result = true };

        popup.IsOpen = false;

    }

}

Then in your footer, bind to two simple commands you expose once on a base view model, and call ShowAsyncCustom from the page. This way TaskCompletionSource boilerplate lives in one place instead of every popup.

Two practical notes from this thread that will save people time:

AutoSizeMode="Height" means WidthRequest / HeightRequest return -1 until the popup opens, so any "center bottom" math has to use a fixed width or be calculated in the Opened event, not before Show().

When using FooterTemplate, the default close-and-return behavior is fully overridden by design (confirmed by Syncfusion). There is no hidden AcceptCommand to bind to, so the wrapper pattern above is the practical workaround until/unless Syncfusion exposes default commands as a feature.


Loader.
Up arrow icon