The key is that you need to cast the PageHandler as IPlatformViewHandler to access the ViewController, as @PureWeen said. To get to the UINavigationItem, you need to look at the ParentViewController at just the right moment in the page's lifecycle. Unfortunately that moment exists somewhere between the page Appearing event and the Loaded event. #22050
The key is that you need to cast the PageHandler as IPlatformViewHandler to access the ViewController, as @PureWeen said. To get to the UINavigationItem, you need to look at the ParentViewController at just the right moment in the page's lifecycle. Unfortunately that moment exists somewhere between the page Appearing event and the Loaded event.
I have been able to approximate the functionality of overriding ViewWillAppear by using the following handler. In my apps I use a base class for each page called CorePage:
public abstract class CorePage : ContentPage { }
public class CorePageHandler : Microsoft.Maui.Handlers.PageHandler
{
protected override void ConnectHandler(Microsoft.Maui.Platform.ContentView nativeView) {
base.ConnectHandler(nativeView);
CorePage.Loaded += OnLoaded;
}
protected override void DisconnectHandler(Microsoft.Maui.Platform.ContentView nativeView) {
CorePage.Loaded -= OnLoaded;
base.DisconnectHandler(nativeView);
}
CorePage CorePage => VirtualView as CorePage;
void OnLoaded(object sender, EventArgs e) => ManageBarButtons();
void ManageBarButtons() {
if (this is IPlatformViewHandler handler
&& handler.ViewController?.ParentViewController?.NavigationItem is UINavigationItem navItem ) {
List<UIBarButtonItem> rightBarButtons = new();
List<UIBarButtonItem> leftBarButtons = new(navItem.LeftBarButtonItems ?? Array.Empty<UIBarButtonItem>());
// manipulate buttons here
navItem.RightBarButtonItems = rightBarButtons.ToArray();
navItem.LeftBarButtonItems = leftBarButtons.ToArray();
}
}
}
Note that I say approximate, because there can be visual artifacts when manipulating the buttons during the ContentPage.Loaded event. My implementation replaces generated UIBarButtonItem objects with new ones using native UIBarButtonSystemItem and SF Symbols (this is iOS after all). I overcame the timing issue with a hack: I save/remove the ToolbarItem objects in ConnectHandler and add manually created UIBarButtonItem objects during the Loaded event. This approach works, but I'm not a fan.
For the PageRenderer functionality to ultimately be obsoleted, MAUI needs to implement access to the UIViewController during ViewWillAppear in a manner that not only we Xamarin Forms developers are accustomed to, but that is also easily discoverable by new programmers coming to .NET MAUI.
I have been able to approximate the functionality of overriding ViewWillAppear by using the following handler. In my apps I use a base class for each page called CorePage:
Note that I say approximate, because there can be visual artifacts when manipulating the buttons during the ContentPage.Loaded event. My implementation replaces generated UIBarButtonItem objects with new ones using native UIBarButtonSystemItem and SF Symbols (this is iOS after all). I overcame the timing issue with a hack: I save/remove the ToolbarItem objects in ConnectHandler and add manually created UIBarButtonItem objects during the Loaded event. This approach works, but I'm not a fan.
For the PageRenderer functionality to ultimately be obsoleted, MAUI needs to implement access to the UIViewController during ViewWillAppear in a manner that not only we Xamarin Forms developers are accustomed to, but that is also easily discoverable by new programmers coming to .NET MAUI.
Originally posted by @agendamatic in https://github.com/dotnet/maui/issues/7174#issuecomment-1244019860