Prompts on top of popup windows in Xamarin and MAUI - xamarin

I have discovered the limitation of displaying prompts when they are invoked from a popup window. Specifically verified with CommunityToolkit.Maui Popups.
Here's the details:
In the Map page I have this handler for the map clicked event:
void mapClicked(object sender, MapClickedEventArgs e) {
var pin = new Pin {
Label = "Here's where it is",
Location = e.Location
};
map.Pins.Add(pin);
}
I wanted to allow the user to edit the pin label when clicking on the it, like so:
pin.InfoWindowClicked += async (s, args) => {
string pinName = ((Pin)s).Label;
await DisplayPromptAsync("Enter new label", "enter new label");
};
However, this didn't work as no DisplayPrompt was shown. I tried running it in the main thread, to no avail either.
UPDATE. I've figured it out, see answer below.

The problem arises when attempting to bring up the prompt from a popup window. Evidently, one can't have a DisplayPromptAsync (or DisplayAlert for that matter) on top of a popup.
On a platform-specific level in iOS the error message reads:
Attempt to present <UIAlertController> on <Microsoft_Maui_Controls_Platform_Compatibility_ShellFlyoutRenderer> (from <Microsoft_Maui_Controls_Platform_Compatibility_ShellFlyoutRenderer>) which is already presenting <CommunityToolkit_Maui_Core_Views_MauiPopup>.

Related

Why are Xamarin Forms.maps Pin not showing information on click in Android?

I have PinsCollection Observablecollection as the itemSource of my forms.map. It loads all the pins in iOS and on tap of each Pin I can see the label and Address. But in Android I can see all the pins, but nothing happens on click of the pin.
If you want to do something when you click the pin, you could use the MarkerClicked . The MarkerClicked event is fired when a pin is tapped.
boardwalkPin.MarkerClicked += async (s, args) =>
{
args.HideInfoWindow = true;
string pinName = ((Pin)s).Label;
await DisplayAlert("Pin Clicked", $"{pinName} was clicked.", "Ok");
};
You could download the source from the link below. https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/map/pins

Why does SkiaSharp Touch SKTouchAction.Moved event not work?

Summary
The Touch event is never raised with the ActionType of SKTouchAction.Moved, but SKTouchAction.Pressed is raised. Why does the .Moved event never get raised?
Detail
I am attempting to create a slider in SkiaSharp. This control will need to update the thumb (the little movable circle) when the user either touches on the slider or drags. This is hosted in a Xamarin Forms app, and I have created a SKCanvasView to draw the slider and to respond to touch events.
I have successfully responded to touch events, so I know the SKCanvasView is receiving some UI events, but the SKTouchAction.Moved is never raised.
Example Code
private SKCanvasView CreateSliderControl()
{
var control = new SKCanvasView();
control.PaintSurface += HandlePaintHeightControl;
control.EnableTouchEvents = true;
control.Touch += (sender, args) =>
{
var pt = args.Location;
switch (args.ActionType)
{
case SKTouchAction.Pressed:
// 1. This code gets hit whenever I touch the canvas
control.InvalidateSurface();
break;
case SKTouchAction.Moved:
// 2. This code never gets hit, even if I push, touch, slide, etc
control.InvalidateSurface();
break;
}
};
control.InputTransparent = false;
return control;
}
As shown above #1 gets hit (I can put a breakpoint there, and my control surface is invalidated). #2 never gets hit ever, but I expect it to get hit when I slide my finger over the control.
What I've Tried
Clean/rebuild to make sure my code actually was being deployed
Upgrade from SkiaSharp 1.60.3 to 1.68.0
All the crazy finger movements I could come up with
Read through https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/graphics/skiasharp/transforms/touch , but that uses XAML to assign an Effect (which I'm not familiar with) and I don't see a TouchEffect class available anywhere in my code to add it to the parent Grid that contains my SkiaCanvasView.
Found a similar issue on SkiaSharp's Github.
Try telling the OS that you want to "continue receiving touch events" by setting the Handled property in the event's args to true.
private SKCanvasView CreateSliderControl()
{
var control = new SKCanvasView();
control.PaintSurface += HandlePaintHeightControl;
control.EnableTouchEvents = true;
control.Touch += (sender, args) =>
{
var pt = args.Location;
switch (args.ActionType)
{
case SKTouchAction.Pressed:
control.InvalidateSurface();
break;
case SKTouchAction.Moved:
control.InvalidateSurface();
break;
}
// Let the OS know that we want to receive more touch events
args.Handled = true;
};
control.InputTransparent = false;
return control;
}

Windows Form Listview is not visually showing selected items

We have a tool that is being integrated into our application. We have some strict borders around us too in that we cannot modify the application except for our extensions. I have searched here, I've searched the internet, but cannot find any postings about this problem.
I have a Windows Form that contains a ListView and our user requires we create a checkbox to Select/Deselect all. I have the event handler for when the check box state changes and call the routine to set everything to Selected.
private void SelectAllEventHandler(object sender, EventArgs e)
{
ChangeState(RadCapListView, SelectAllRadcap.Checked);
}
private void ChangeState(SWF.ListView control, bool state)
{
if (control.CheckBoxes)
{
control.Items.OfType<SWF.ListViewItem>().ToList()
.ForEach(item => item.Checked = state);
}
else
{
control.Items.OfType<SWF.ListViewItem>().ToList()
.ForEach(item => item.Selected = state);
}
control.Refresh();
}
Going into debug mode all items are marked as selected.
Also at the control level SelectedItems is properly updated.
The issue is that visually the control just will not highlight the selected items like we have our WPF forms doing. As you can see in the code I also tried to refresh the control hoping that would show items selected, but no joy.
Has anyone solved this problem in getting selected items to display properly?
Thank!
Instead of using control.Refresh(), try control.Focus().

Xamarin app crashes on ObservableCollection.Add?

I have an Xamarin.Forms app running on iOS simulator that just stops as soon as it hits code which adds a new member to an observable collection that is the template source for a CarouselView. Oddly, it doesnt happen immediately, but only when I add more items to the collection when the user gets close to the end of the carousel. I can't trap the error in a try catch block. In debug mode, when I stop at the line in question and either step in or step over, the app just closes and goes back to the home screen. I recently updated my packages, maybe there is some issue there?
Code as follows:
private ObservableCollection<ResultsScroller> mySource;
public void PopulateResultsPages(List<NominalResult> resultList)
{
foreach (var nr in resultList)
{
var template = new ResultsScroller();
template.LoadData(nr);
try
{
mySource.Add(template); // <----app quits here
}
catch (System.Exception e)
{
System.Diagnostics.Debug.WriteLine(e.Message);
}
}
lastPosition = mySource.Count - 1;
}
initialize observablecollevtion mySource in constructor like this
mySource = new ObservableCollection<ResultsScroller>();
after that add item in it.
Currently you have to somehow programmatically make the ListView appear before adding an item. If the ListView is inside a tab that is not visible, show it by setting the CurrentPage Property. If it is in a MasterDetailPage, you could try showing it by toggling the IsPresented Property.
An upcoming Update of XF should fix this issue:
- https://github.com/xamarin/Xamarin.Forms/issues/1542
- https://github.com/xamarin/Xamarin.Forms/issues/1927

Open a New Frame Window From MainPage in Windows 10 Universal App?

How to open a new frame window which contains another xaml page when I click a button from the main window in universal app?
You can check out a sample on how to do this from the Offical Microsoft Samples on GitHub as can be found here but I'll summarize quickly here. Another simpler implementation can be found on Mike Taulty's Blog.
Since you haven't specified a development language I will assume C# and XAML.
Create your button in XAML which will be clicked to create a new window:
<Button
Content="Create"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Click="OnCreate" />
In the code behind, add your OnCreate click handler:
async void OnCreate(object sender, RoutedEventArgs e)
{
CoreApplicationView newCoreView = CoreApplication.CreateNewView();
ApplicationView newAppView = null;
int mainViewId = ApplicationView.GetApplicationViewIdForWindow(
CoreApplication.MainView.CoreWindow);
await newCoreView.Dispatcher.RunAsync(
CoreDispatcherPriority.Normal,
() =>
{
newAppView = ApplicationView.GetForCurrentView();
Window.Current.Content = new SubWindowUserControl();
Window.Current.Activate();
});
await ApplicationViewSwitcher.TryShowAsStandaloneAsync(
newAppView.Id,
ViewSizePreference.UseHalf,
mainViewId,
ViewSizePreference.UseHalf);
}
This creates a new window, and fetches the application view ID of your original window for you to reference. It then awaits a dispatched thread to run (in the UI thread of the new window) to get the new view the window contains which it adds a new SubWindowUserControl to, programatically, and is then activated (you MUST remember to do this). The new window is then shown in a new standalone window using some standard parameters.
Check out the API documentation here for more details on the ApplicationViewSwitcher class.
To take this code and make it show a new XAML page you can create your new page and change the async task running on the new window in the OnCreate code as follows:
await newCoreView.Dispatcher.RunAsync(
CoreDispatcherPriority.Normal,
() =>
{
newAppView = ApplicationView.GetForCurrentView();
Window.Current.Content = new Frame();
(Window.Current.Content as Frame).Navigate(typeof(<your_page>));
Window.Current.Activate();
});
This, instead of showing a new custom XAML element as its content, creates a new Frame which is then navigated to show your XAML page.
Hope this helps!

Resources