This is a migrated thread and some comments may be shown as answers.

SideDrawer on TabbedPage possible?

7 Answers 363 Views
SideDrawer
This is a migrated thread and some comments may be shown as answers.
VincentH
Top achievements
Rank 1
VincentH asked on 26 Oct 2016, 11:36 AM

I need to add a side drawer to an app that has a Xamarin Forms TabbedPage as it's main page - I am aiming for the same navigation as e.g. the Twitter app on Android.

However the MainContent property of the RadSideDrawer is of type View instead of Page so I cannot set it to a TabbedPage instance.

-> Is it possible to use a TabbedPage with RadSideDrawer? If yes, how?

If this is not possible, would the standard Xamarin Forms MasterDetailPage, offer an alternative?
It has Master and Detail properties of type Page and it is used to create a side drawer in e.g. the Hanselman.Forms app (although not on a TabbedPage).

7 Answers, 1 is accepted

Sort by
0
VincentH
Top achievements
Rank 1
answered on 28 Oct 2016, 09:42 AM

PS When I create a single header instance and return that each time in the GroupHeaderTemplate (see code below), the header looks OK but I still wonder whether this invoke twice behaviour is by design or a bug?

var header = new Label { HorizontalTextAlignment = TextAlignment.Center, Text = "Welcome to Xamarin Forms!" };
GroupHeaderTemplate = new DataTemplate(() => {
  return header; // This is called twice instead of once so do not create new view instances here
});


0
VincentH
Top achievements
Rank 1
answered on 31 Oct 2016, 07:50 AM

Pls ignore my above reply; it belongs to another question

I would still like to see my question on SideDrawer answered!

0
Ves
Telerik team
answered on 31 Oct 2016, 11:37 AM
Hi Vincent

One possible approach here would be to place RadSideDrawer within a page and use it as Master in a MasterDetailPage and use a TabbedPage as Detail. Alternatively, you can use only TabbedPage, but you will need to place one RadSideDrawer control within every child page.

Best regards,
Ves
Telerik by Progress
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
EHG
Top achievements
Rank 1
answered on 12 Nov 2017, 11:26 AM

Hi,

Can you provide some sample code to implement the possible way that you described.

Thank you,

0
Lance | Manager Technical Support
Telerik team
answered on 13 Nov 2017, 05:38 PM
Hi Emaar,

I'm assuming you mean this part of Vesselin's response?

"place RadSideDrawer within a page and use it as Master in a MasterDetailPage and use a TabbedPage as Detail"

Demo

Start with the Xamarin Master Detail Page template:




Put the RadSideDrawer in the MasterPage

<ContentPage ...
    x:Class="MasterDetailPlacement.Portable.Views.MasterDetailPage1Master"
    Title="Master">
 
    <primitives:RadSideDrawer x:Name="drawer" DrawerLength="200">
        <primitives:RadSideDrawer.DrawerContent>
            <ListView  ItemsSource="{Binding MenuItems}">
            </ListView>
        </primitives:RadSideDrawer.DrawerContent>
    </primitives:RadSideDrawer>
     
</ContentPage>


DetailPage

            xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
            x:Class="MasterDetailPlacement.Portable.Views.MasterDetailPage1Detail"
            Title="Detail">
    <!--Pages can be added as references or inline-->
    <ContentPage Title="Tab 1" />
    <ContentPage Title="Tab 2" />
    <ContentPage Title="Tab 3" />
</TabbedPage>


and here's the MasterDetail root:

<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MasterDetailPlacement.Portable.Views.MasterDetailPage1"
             xmlns:pages="clr-namespace:MasterDetailPlacement.Portable.Views">
  <MasterDetailPage.Master>
    <pages:MasterDetailPage1Master x:Name="MasterPage" />
  </MasterDetailPage.Master>
  <MasterDetailPage.Detail>
    <NavigationPage>
      <x:Arguments>
        <pages:MasterDetailPage1Detail />
      </x:Arguments>
    </NavigationPage>
  </MasterDetailPage.Detail>
</MasterDetailPage>


Finally, you'll of course have to wire up the navigation a little differently because the Master Detail template uses a NavigationPage instead of a Tabbed page, but that's trivial.  Here is the documentaiton on how to use a TabbedPage, there is also a full demo here.

In a nutshell, you can get the index of the selected item from the ListView in the SideDrawer and then use that index to select the item on the TabbedPage

public partial class MasterDetailPage1 : MasterDetailPage
{
    public MasterDetailPage1()
    {
        InitializeComponent();
        MasterPage.ListView.ItemSelected += ListView_ItemSelected;
    }
 
    private void ListView_ItemSelected(object sender, SelectedItemChangedEventArgs e)
    {
        // UPDATED for use with TabbedPage as Detail
        if (e.SelectedItem is MasterDetailPage1MenuItem item)
        {
            // get the index of the selected item
            var vm = MasterPage.BindingContext as MasterDetailPage1Master.MasterDetailPage1MasterViewModel;
            var index = vm?.MenuItems.IndexOf(item);
 
            if (index == null) return;
 
            if ((Detail as NavigationPage)?.CurrentPage is TabbedPage tabbedPage)
            {
                tabbedPage.SelectedItem = tabbedPage.Children[(int)index];
            }
 
            IsPresented = false;
            MasterPage.ListView.SelectedItem = null;
        }
    }
}


Summary

Ultimately, the RadSideDrawer was not designed for Page navigation as the SideDrawer's MainContent is of type View, and does not work for content of type Page. The above approach may cause more problems than just using the MasterPage as is (with just a ListView/RadListView).

For an alternate solution to Page navigation, take a look at our Tagit example for inspiration.

Regards,
Lance | Tech Support Engineer, Sr.
Progress Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Hamid
Top achievements
Rank 1
answered on 03 Dec 2018, 09:48 AM

I found a solution that doesn't need to use MasterDetailPage:

By having a global Drawer in Holder.SideDrawer as this line, you don't need to define it on every tabbedPage or contentPage:

public static RadSideDrawer SideDrawer { get; set; }

This is the Xaml code for the toolbar item in the tabbed pages:

 <TabbedPage.ToolbarItems>
    <ToolbarItem x:Name="SideMenuToolbarItem" Priority="1" Order="Primary" Icon="sideMenuIcon.png" Clicked="SideMenuToolbarItem_OnClicked" />
  </TabbedPage.ToolbarItems>

 

In the Tabbed pages these two methods should be written:

private void SideMenuToolbarItem_OnClicked(object sender, EventArgs e)
{
CurrentPage = Helper.SideBarMenuItemOnClicked((ContentPage)CurrentPage);
}

protected override void OnCurrentPageChanged()
{
base.OnCurrentPageChanged();

if (Holder.SideDrawer != null)
{
Holder.SideDrawer.IsOpen = false;
Holder.SideDrawer = null;
}
}

By making the Holder.SideDrawer null, we make sure it won't left open when switching tabs.

 

This is the definition of Helper.SideBarMenuItemOnClicked:

public static Page SideBarMenuItemOnClicked(ContentPage page)
{
if (Holder.SideDrawer != null && Holder.SideDrawer.IsOpen)
{
Holder.SideDrawer.IsOpen = false;
return page;
}

page.Content = SideBarMenuItemOnClicked(page.Content);
return page;
}

public static View SideBarMenuItemOnClicked(View content)
{
if (Holder.SideDrawer != null && Holder.SideDrawer.IsOpen)
{
Holder.SideDrawer.IsOpen = false;
return content;
}

var drawerContent = new SideBarMenuView(content);

Holder.SideDrawer = new RadSideDrawer
{
MainContent = content,
DrawerContent = drawerContent,
DrawerLength = 250,
DrawerLocation = SideDrawerLocation.Right,
DrawerTransitionType = SideDrawerTransitionType.SlideInOnTop,
IsOpen = true
};

content = Holder.SideDrawer;
return content;
}

The last method can also be used for normal content pages.

Finally, it's up to you to define SideBarMenuView however you need:

 

[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class SideBarMenuView : ContentView
{
public SideBarMenuView(View content)
{
InitializeComponent();

}

}

 

 

Good luck.

 

 

 

0
Nethra
Top achievements
Rank 1
answered on 03 Jan 2019, 06:37 PM
I'm looking for the same feature. I tried implementing as per your solution but,not working. Please can you provide the link to GitHub if you have.
Tags
SideDrawer
Asked by
VincentH
Top achievements
Rank 1
Answers by
VincentH
Top achievements
Rank 1
Ves
Telerik team
EHG
Top achievements
Rank 1
Lance | Manager Technical Support
Telerik team
Hamid
Top achievements
Rank 1
Nethra
Top achievements
Rank 1
Share this question
or