How do implement panel feature in Xamarin.forms

2019-09-11 03:34发布

Like in Windows Forms we can add multiple panels in the same Form and based on some condition show and hide particular panel. Is there any control in Xamarin.Forms which can be used like this?

The main reason behind this is, I have 3 tabs on a page. I am using buttons for tabs and not tabbed pages as design of tabbed bar is not what my client wants. So I have 3 pages say Page A, Page B, Page C and each of the page has 3 tabs to go to respective page. If user is on Page A and fills some sort of data(which is not yet saved) and wants to go to Page B and then on Page B he fills in some more details and then without saving data on Page B when he comes back to Page A all the details filled by user on Page A and Page B has to be available.

Hence If I use multiple pages for this then the data will be lost when I redirect to new page. So Is there any way by which I have multiple panels and hide 1st panel when 2nd panel is visible which will not clear any data and hence I can achieve what I want.

2条回答
We Are One
2楼-- · 2019-09-11 04:18

You can just hide the panels that aren't being used (using the IsVisible property) - this pulls them out of the visual tree but does not release them from memory.

If you create a Content View for each page, then you can easily use them in your main UI such as in this example. Even though we are hiding the individual panels they will still remain in memory while hidden:

MyView.cs (this could be anything you want in your panels):

using System;
using Xamarin.Forms;

namespace FormsSandbox
{
    public class MyView : ContentView
    {
        public static BindableProperty TextProperty = BindableProperty.Create("Text", typeof(string), typeof(MyView), 
            String.Empty, BindingMode.Default, null, TextChanged);

        public string Text {
            get {
                return (string)GetValue (TextProperty);
            }
            set {
                SetValue (TextProperty, value);
            }
        }

        private Label _contentLabel;

        public MyView ()
        {
            _contentLabel = new Label {
                FontSize = 56,
                FontAttributes = FontAttributes.Bold,
                HorizontalTextAlignment = TextAlignment.Center,
                VerticalTextAlignment = TextAlignment.Center
            };
            Content = _contentLabel;
        }

        static void TextChanged (BindableObject bindable, object oldValue, object newValue)
        {
            var view = (MyView)bindable;
            view._contentLabel.Text = (newValue ?? "").ToString ();
        }
    }
}

XamlPage.xaml (main UI page):

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:sandbox="clr-namespace:FormsSandbox"
    x:Class="FormsSandbox.XamlPage">
    <ContentPage.Padding>
        <OnPlatform x:TypeArguments="Thickness" iOS="0,20,0,0" Android="0" WinPhone="0"/>
    </ContentPage.Padding>

    <Grid RowSpacing="0" ColumnSpacing="0">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>

        <Button Text="1" Clicked="ButtonClicked" x:Name="Button1" Grid.Column="0" />
        <Button Text="2" Clicked="ButtonClicked" x:Name="Button2" Grid.Column="1" />
        <Button Text="3" Clicked="ButtonClicked" x:Name="Button3" Grid.Column="2" />

        <sandbox:MyView Text="1" x:Name="View1" Grid.Row="1" Grid.ColumnSpan="3" />
        <sandbox:MyView Text="2" x:Name="View2" Grid.Row="1" Grid.ColumnSpan="3" />
        <sandbox:MyView Text="3" x:Name="View3" Grid.Row="1" Grid.ColumnSpan="3" />
    </Grid>

</ContentPage>

XamlPage.xaml.cs:

using System;
using Xamarin.Forms;

namespace FormsSandbox
{
    public partial class XamlPage : ContentPage
    {
        public XamlPage ()
        {
            InitializeComponent ();
            SelectButton (Button1);
        }

        void SelectButton(Button button)
        {
            View view = null;
            if (button == Button1)
                view = View1;
            if (button == Button2)
                view = View2;
            if (button == Button3)
                view = View3;
            View1.IsVisible = View1 == view;
            View2.IsVisible = View2 == view;
            View3.IsVisible = View3 == view;
            Button1.TextColor = (Button1 == button) ? Color.Accent.AddLuminosity(0.18) : (Color)Button.TextColorProperty.DefaultValue;
            Button2.TextColor = (Button2 == button) ? Color.Accent.AddLuminosity(0.18) : (Color)Button.TextColorProperty.DefaultValue;
            Button3.TextColor = (Button3 == button) ? Color.Accent.AddLuminosity(0.18) : (Color)Button.TextColorProperty.DefaultValue;
            Button1.BackgroundColor = (Button1 == button) ? Color.Silver.AddLuminosity(0.18) : Color.Silver.AddLuminosity(0.1);
            Button2.BackgroundColor = (Button2 == button) ? Color.Silver.AddLuminosity(0.18) : Color.Silver.AddLuminosity(0.1);
            Button3.BackgroundColor = (Button3 == button) ? Color.Silver.AddLuminosity(0.18) : Color.Silver.AddLuminosity(0.1);
        }

        void ButtonClicked (object sender, EventArgs e)
        {
            SelectButton ((Button)sender);
        }
    }
}

Running example

查看更多
混吃等死
3楼-- · 2019-09-11 04:26

You can save this data to a cache and load it from there.

public static class MyDataCache 
{
    public static MyData MyData { get; } = new MyData();
}

// in your pages
protected override void OnAppearing()
{            
    base.OnAppearing();
    // set data from MyDataCache.MyData
    MyProperty = MyDataCache.MyData.MyProperty;
}

protected override void OnDisappearing()
{            
    base.OnDisappearing();
    // set data to MyDataCache.MyData
    MyDataCache.MyData.MyProperty = MyProperty;
}

But be aware: It's just a memory cache. If the App gets tombstoned, the data will be lost. You can try this approach first and see if its fits your need. After that, you should store the data in a temporary storage (e.g. with Akavache). You should not rebuild this page navigation behavior with something custom.

查看更多
登录 后发表回答