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.
Looks like there is the PopupStyle property:
<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. 🤔
Additionally, it would be ideal for us to:
- Open the Popup so that it is aligned centered bottom of the screen.
- Move the close button the left
- Stretch the OneButton in the footer so it's 100% width
Is this possible?
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
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.
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. 👍
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.
Attachment: SfPopupSample_(2)_84310a3e.zip
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.
Hi Mike-E,
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.
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 :
|
{ 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; }
{ _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
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. 🙏
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. 🙏
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> |
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.
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.
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
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.
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.
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.
- 20 Replies
- 4 Participants
- Marked answer
-
MI Mike-E
- Jun 20, 2025 03:30 PM UTC
- Jun 1, 2026 04:28 AM UTC