XAM-Consulting / SlideOverKit

Easily Create Awesome Slideover's in Xamarin.Forms
Apache License 2.0
394 stars 120 forks source link

ShowMenuAction targeting null #40

Open kcox40 opened 7 years ago

kcox40 commented 7 years ago

I created a Control Template in my PCL App.xaml and App.xaml.cs to create a custom header for my application. I was just messing around to see if I could add a universal slide menu by having App.xaml.cs implement IMenuContainerPage. I set it all up, but the ShowMenuAction?.Invoke() targets null when I use it in the App class. Is this because its not actually a Page? or is there a way I could actually invoke the ShowMenuAction and HideMenuAction directly from the App class?

`using System; using Xamarin.Forms; using static EngApp.MainActivityPage; using SlideOverKit;

namespace EngApp { public partial class App : Application, IMenuContainerPage {

    public Action HideMenuAction
    {
        get;
        set;
    }

    public Action ShowMenuAction
    {
        get;
        set;
    }

    public SlideMenuView SlideMenu
    {
        get;
        set;
    }
    public SlideRightFilterView filterMenu;
    public NavigationPage NavPage { get; private set; }
    public App()
    {

        InitializeComponent();
        MainPage = new DeviceFinder();
        this.SlideMenu = new SlideRightFilterView();

    }

    protected override void OnStart()
    {
        // Handle when your app starts
    }

    protected override void OnSleep()
    {
        // Handle when your app sleeps
    }

    protected override void OnResume()
    {
        // Handle when your app resumes
    }
    void OpenFilter(object sender, EventArgs args)
    {
        if (this.SlideMenu.IsShown)
        {
            HideMenuAction?.Invoke();
        }
        else
        {
            ShowMenuAction?.Invoke();

        }
    }
}

}`

XAML CONTROL TEMPLATE

`<?xml version="1.0" encoding="utf-8" ?> <Application xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="EngApp.App">

<Application.Resources >

    <!-- Application resource dictionary -->
    <ResourceDictionary >
        <ControlTemplate x:Key="MainPageTemplate" >
            <Grid VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" ColumnSpacing="0">
                <Grid.RowDefinitions>
                    <RowDefinition Height="50"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width=".3*"/>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="1.5*"/>
                    <ColumnDefinition Width=".4*"/>
                    <ColumnDefinition Width=".4*"/>

                </Grid.ColumnDefinitions>
                <Image x:Name="arrow" Source="arrow.png" Aspect="AspectFit" BackgroundColor="Transparent" Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="1" Margin="12,17,0,17" HorizontalOptions="StartAndExpand">
                    <Image.GestureRecognizers>
                        <TapGestureRecognizer Tapped="OpenMenu"/>
                    </Image.GestureRecognizers>
                </Image>
                <Image Source="eaton_corporation_logo.png" Aspect="AspectFit" BackgroundColor="Transparent" Grid.Column="1" Grid.Row="0" Grid.ColumnSpan="1" HorizontalOptions="StartAndExpand">
                    <Image.GestureRecognizers>
                        <TapGestureRecognizer Tapped="OpenMenu"/>
                    </Image.GestureRecognizers>
                </Image>
                <StackLayout  Grid.Column="3" Grid.Row="0" Padding="10, 0, 10, 0" >

                    <Picker x:Name="ChannelPicker" SelectedIndexChanged="SelectedChannel" TextColor="DarkGray" SelectedIndex="0">
                        <Picker.Items>
                            <x:String>Channel 11</x:String>
                            <x:String>Channel 12</x:String>
                            <x:String>Channel 13</x:String>
                            <x:String>Channel 14</x:String>
                            <x:String>Channel 15</x:String>
                            <x:String>Channel 16</x:String>
                            <x:String>Channel 17</x:String>
                            <x:String>Channel 18</x:String>
                            <x:String>Channel 19</x:String>
                            <x:String>Channel 20</x:String>
                            <x:String>Channel 21</x:String>
                            <x:String>Channel 22</x:String>
                            <x:String>Channel 23</x:String>
                            <x:String>Channel 24</x:String>
                            <x:String>Channel 25</x:String>
                            <x:String>Cahnnel 26</x:String>
                        </Picker.Items>
                    </Picker>
                </StackLayout>
                <Image Source="freezedark.png" Grid.Column="4" Grid.Row="0" HorizontalOptions="EndAndExpand" Margin="0,10,4,10">
                    <Image.GestureRecognizers>
                        <TapGestureRecognizer Tapped="Freeze"/>
                    </Image.GestureRecognizers>
                </Image>
                <Image Source="filter.png" Grid.Column="5" Grid.Row="0" HorizontalOptions="EndAndExpand" Margin="5,12,5,12">
                    <Image.GestureRecognizers>
                        <TapGestureRecognizer Tapped="OpenFilter"/>
                    </Image.GestureRecognizers>
                </Image>

                <ContentPresenter x:Name ="notToolBar" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" Grid.Column="0"  Grid.Row="1" Grid.ColumnSpan="6"/>
            </Grid>
        </ControlTemplate>
    </ResourceDictionary>

</Application.Resources>

`

jessejiang0214 commented 7 years ago

Yes, the container must be a Page. Why do you want to show popup in App class?

kcox40 commented 7 years ago

I created a custom toolbar as a control template in the App class (it can be applied to any page and has custom images and controls ):

`<?xml version="1.0" encoding="utf-8" ?> <Application xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="EngApp.App">

<Application.Resources >

    <!-- Application resource dictionary -->
    <ResourceDictionary >
        <ControlTemplate x:Key="MainPageTemplate" >
            <Grid VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" ColumnSpacing="0">
                <Grid.RowDefinitions>
                    <RowDefinition Height="50"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width=".3*"/>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="1.5*"/>
                    <ColumnDefinition Width=".4*"/>
                    <ColumnDefinition Width=".4*"/>

                </Grid.ColumnDefinitions>
                <Image x:Name="arrow" Source="arrow.png" Aspect="AspectFit" BackgroundColor="Transparent" Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="1" Margin="12,17,0,17" HorizontalOptions="StartAndExpand">
                    <Image.GestureRecognizers>
                        <TapGestureRecognizer Tapped="OpenMenu"/>
                    </Image.GestureRecognizers>
                </Image>
                <Image Source="eaton_corporation_logo.png" Aspect="AspectFit" BackgroundColor="Transparent" Grid.Column="1" Grid.Row="0" Grid.ColumnSpan="1" HorizontalOptions="StartAndExpand">
                    <Image.GestureRecognizers>
                        <TapGestureRecognizer Tapped="OpenMenu"/>
                    </Image.GestureRecognizers>
                </Image>
                <StackLayout  Grid.Column="3" Grid.Row="0" Padding="10, 0, 10, 0" >

                    <Picker x:Name="ChannelPicker" SelectedIndexChanged="SelectedChannel" TextColor="DarkGray" SelectedIndex="0">
                        <Picker.Items>
                            <x:String>Channel 11</x:String>
                            <x:String>Channel 12</x:String>
                            <x:String>Channel 13</x:String>
                            <x:String>Channel 14</x:String>
                            <x:String>Channel 15</x:String>
                            <x:String>Channel 16</x:String>
                            <x:String>Channel 17</x:String>
                            <x:String>Channel 18</x:String>
                            <x:String>Channel 19</x:String>
                            <x:String>Channel 20</x:String>
                            <x:String>Channel 21</x:String>
                            <x:String>Channel 22</x:String>
                            <x:String>Channel 23</x:String>
                            <x:String>Channel 24</x:String>
                            <x:String>Channel 25</x:String>
                            <x:String>Cahnnel 26</x:String>
                        </Picker.Items>
                    </Picker>
                </StackLayout>
                <Image Source="freezedark.png" Grid.Column="4" Grid.Row="0" HorizontalOptions="EndAndExpand" Margin="0,10,4,10">
                    <Image.GestureRecognizers>
                        <TapGestureRecognizer Tapped="Freeze"/>
                    </Image.GestureRecognizers>
                </Image>
                <Image Source="filter.png" Grid.Column="5" Grid.Row="0" HorizontalOptions="EndAndExpand" Margin="5,12,5,12">
                    <Image.GestureRecognizers>
                        <TapGestureRecognizer Tapped="**OpenFilter**"/>
                    </Image.GestureRecognizers>
                </Image>

                <ContentPresenter x:Name ="notToolBar" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" Grid.Column="0"  Grid.Row="1" Grid.ColumnSpan="6"/>
            </Grid>
        </ControlTemplate>
    </ResourceDictionary>

</Application.Resources>

`

And the "OpenFilter" tapped event (handled in App.aaml.cs) is what should open the filter side menu.

I can just use messaging center or an event to tell it to open the menu in whatever page is open in the "ContentPresenter" (the non toolbar area). But I already have another menu defined on that page using SlideOverKit. I was hoping this could be a universal workaround to the fact that slideOverKit only allows one menu per page. I've already managed to get two menus working (by using MasterDetailPage + SlideOverKit) but I need a third menu that slides out from the right. I thought that if this one was called from App.xaml/cs that it might be able to act as a third menu. Like I assumed it only works if the container is a Page...

I also posted my issue (worded differently) on the Xamarin forum: https://forums.xamarin.com/discussion/comment/285072#Comment_285072

If you have any suggestions to get the third menu please let me know.

Finneyv commented 6 years ago

@jessejiang0214 Hey I know this issue is 6 months old but I've encountered this same issue with a MasterDetailPage that implements the IMenuContainerPage interface. Here's my code:

`

public class MasterDetailMenuPage : MasterDetailPage, IMenuContainerPage { public MasterDetailMenuPage() { this.MasterBehavior = MasterBehavior.Split; }

    public Action HideMenuAction { get; set; }

    public Action ShowMenuAction { get; set; }

    SlideMenuView slideMenu;
    public SlideMenuView SlideMenu
    {
        get
        {
            return slideMenu;
        }

        set
        {
            if (slideMenu != null)
                slideMenu.Parent = null;
            slideMenu = value;
            if (slideMenu != null)
                slideMenu.Parent = this;
        }
    }

    public void ShowMenu()
    {
        ShowMenuAction?.Invoke();
    }

    public void HideMenu()
    {
        HideMenuAction?.Invoke();
    }
}

` Like with kcox40's issue the "ShowMenuAction?.Invoke();" always returns null for it's target. The strange thing is that I only experience this on Android and it only started happening after I upgraded to Xamarin Forms 2.5.0.121934.

Finneyv commented 6 years ago

OK I've figured what I was doing wrong. Instead of targeting the MasterDetailsPage itself I had to target the Master page. I was doing this on iOS but not on Android. Thank you for your time.

shreyans-wakekar commented 6 years ago

ShowMenuAction targeting null in ViewModel. Can anybody help ? How to show hide menu in viewmodel..

ojuniour commented 6 years ago

im getting same issue. @Finneyv solution is very clear. Can you elaborate on fix, please/ Thanks.

EDIT: stupid me. I figured it out. In the renderer (typeof() at the top) you have to edit and match the the calling page.