Jak przełączać strony w Xamarin.Forms?

99

Jak przełączać się między stronami w Xamarin Forms?

Moja strona główna to ContentPage i nie chcę przełączać się na coś w rodzaju strony z kartami.

Udało mi się to zrobić pseudo, znajdując elementy nadrzędne kontrolek, które powinny uruchamiać nową stronę, dopóki nie znajdę ContentPage, a następnie zamieniam zawartość z kontrolkami na nową stronę. Ale to wydaje się naprawdę niechlujne.

Eric
źródło
Odpowiedzi na to pytanie było już wiele, aby zobaczyć, jak można to zrobić za pomocą wzorca strukturalnego MVVM, zapoznaj się z tym stackoverflow.com/a/37142513/9403963
Alireza Sattari

Odpowiedzi:

67

Xamarin.Forms obsługuje wiele wbudowanych hostów nawigacji:

  • NavigationPage, gdzie wsuwa się następna strona,
  • TabbedPage, ten, którego nie lubisz
  • CarouselPage, która umożliwia przełączanie lewej i prawej strony na następną / poprzednią stronę.

Co więcej, wszystkie strony obsługują również, PushModalAsync()które po prostu przesuwają nową stronę na istniejącą.

Na sam koniec, jeśli chcesz mieć pewność, że użytkownik nie może wrócić do poprzedniej strony (za pomocą gestu lub przycisku sprzętowego Wstecz), możesz zachować to samo Pagewyświetlane i zastąpić jegoContent .

Sugerowane opcje zamiany strony głównej również działają, ale będziesz musiał traktować to inaczej dla każdej platformy.

Stephane Delcroix
źródło
PushModalAsync wydaje się być częścią nawigacji, prawda? Nie mogę dowiedzieć się, jak dostać się do obiektu / klasy Navigation. Zakładam, że muszę uzyskać dostęp do czegoś, co implementuje INavigation, ale co?
Eric
Jeśli Twoja strona jest zawarta w NavigationPage, powinieneś mieć dostęp do właściwości Navigation z poziomu swojej strony
Jason,
1
Kiedy zacząłem używać NavigationPage, wszystko się ułożyło. Dzięki
Eric
1
@stephane, proszę powiedz, czy moja pierwsza strona to CarouselPage, a druga masterDetailPage, to jak mogę zmienić stronę stackoverflow.com/questions/31129845/ ...
Atul Dhanuka
64

W klasie App możesz ustawić MainPage na stronę nawigacyjną i ustawić stronę główną na swoją ContentPage:

public App ()
{
    // The root page of your application
    MainPage = new NavigationPage( new FirstContentPage() );
}

Następnie w pierwszym wywołaniu ContentPage:

Navigation.PushAsync (new SecondContentPage ());
David Douglas
źródło
Zrobiłem to, ale nadal strona główna jest stroną domyślną, która się otwiera. Żadna strona, którą ustawiłem na stronę główną, nie ma żadnego efektu. Otwieram tylko pierwszą ustawioną stronę. Jaki jest problem?
Behzad
Program Visual Studio sugeruje importowanie Android.Content.Resdo nawigacji. To nie wydaje się być właściwe, skąd mam to zaimportować?
Christian
41

Jeśli twój projekt został skonfigurowany jako projekt formularzy PCL (i najprawdopodobniej również jako formularze udostępnione, ale nie próbowałem tego), istnieje klasa App.cs, która wygląda następująco:

public class App
{
    public static Page GetMainPage ()
    {     
        AuditorDB.Model.Extensions.AutoTimestamp = true;
        return new NavigationPage (new LoginPage ());
    }
}

możesz zmodyfikować GetMainPagemetodę, aby zwrócić nową TabbedPaged lub inną stronę, którą zdefiniowałeś w projekcie

Od tego momentu możesz dodawać polecenia lub programy obsługi zdarzeń, aby wykonywać kod i robić

// to show OtherPage and be able to go back
Navigation.PushAsync(new OtherPage());

// to show AnotherPage and not have a Back button
Navigation.PushModalAsync(new AnotherPage()); 

// to go back one step on the navigation stack
Navigation.PopAsync();
Sten Petrov
źródło
3
To nie przełącza między stronami. To tylko zmienia, która strona jest ładowana początkowo.
dakamojo
Twoje pytanie dotyczyło strony głównej. zobacz zaktualizowaną odpowiedź na przykłady nawigacji
Sten Petrov
Co do cholery jest Navigationw tym przykładzie? - Czy to obiekt, który gdzieś stworzyłeś? - Nie widzę tego w tym przykładzie kodu.
BrainSlugs83
Nawigacja jest własnością na stronie
Sten Petrov
dzięki; FTR PushAsync()nie działał dla mnie, podczas gdy PushModalAsync()tak
knocte
23

Wsuń nową stronę na stos, a następnie usuń bieżącą stronę. Powoduje to zmianę.

item.Tapped += async (sender, e) => {
    await Navigation.PushAsync (new SecondPage ());
    Navigation.RemovePage(this);
};

Najpierw musisz być na stronie nawigacji:

MainPage = NavigationPage(new FirstPage());

Przełączanie treści nie jest idealne, ponieważ masz tylko jedną dużą stronę i jeden zestaw zdarzeń na stronie, takich jak OnAppearing ect.

Daniel Roberts
źródło
Navigation.RemovePage();nie jest obsługiwany w systemie Android.
Rohit Vipin Mathews
1
Navigation.RemovePage (strona); działa w systemie Android, najpierw musi znajdować się wewnątrz strony nawigacyjnej.
Daniel Roberts,
Używam go szeroko w moim projekcie w Forms 1.4.2. Być może naprawili błąd lub po prostu miałem szczęście i jeszcze go nie trafiłem.
Daniel Roberts,
Mam najnowszą wersję i mogę ją odtworzyć. Więc uważam, że masz zbyt dużo szczęścia.
Rohit Vipin Mathews
2
Przydatna wskazówka - aby usunąć przejścia przy zmianie strony, dodaj fałsz jako drugi parametr:await Navigation.PushAsync(new SecondPage(),false);
Damian Green
8

Jeśli nie chcesz przechodzić do poprzedniej strony, tj. Nie pozwól użytkownikowi powrócić do ekranu logowania po zakończeniu autoryzacji, możesz użyć;

 App.Current.MainPage = new HomePage();

Jeśli chcesz włączyć funkcję wsteczną, po prostu użyj

Navigation.PushModalAsync(new HomePage())
Baqer Naqvi
źródło
4

Wygląda na to, że ten wątek jest bardzo popularny i będzie smutno nie wspomnieć, że istnieje alternatywny sposób - ViewModel First Navigation. Większość frameworków MVVM, które go używają, jednak jeśli chcesz zrozumieć, o co chodzi, kontynuuj czytanie.

Cała oficjalna dokumentacja platformy Xamarin.Forms przedstawia proste, ale nieco inne niż MVVM czyste rozwiązanie. Dzieje się tak dlatego, że Page(Widok) nie powinien nic wiedzieć o tym ViewModeli odwrotnie. Oto świetny przykład tego naruszenia:

// C# version
public partial class MyPage : ContentPage
{
    public MyPage()
    {
        InitializeComponent();
        // Violation
        this.BindingContext = new MyViewModel();
    }
}

// XAML version
<?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:viewmodels="clr-namespace:MyApp.ViewModel"
    x:Class="MyApp.Views.MyPage">
    <ContentPage.BindingContext>
        <!-- Violation -->
        <viewmodels:MyViewModel />
    </ContentPage.BindingContext>
</ContentPage>

Jeśli masz dwustronicową aplikację, to podejście może być dla Ciebie dobre. Jeśli jednak pracujesz nad rozwiązaniem dla dużego przedsiębiorstwa, lepiej wybierz ViewModel First Navigationpodejście. Jest to nieco bardziej skomplikowane, ale znacznie czystsze podejście, które umożliwia nawigację między ( ViewModelszamiast nawigacji) między Pages(Widokami). Jedną z zalet oprócz wyraźnego oddzielenia obaw jest to, że można łatwo przekazywać parametry do kolejnychViewModel lub wykonać kod inicjujący asynchroniczny zaraz po nawigacji. Teraz do szczegółów.

(Postaram się maksymalnie uprościć wszystkie przykłady kodu).

1. Przede wszystkim potrzebujemy miejsca, w którym moglibyśmy zarejestrować wszystkie nasze obiekty i opcjonalnie zdefiniować ich żywotność. W tym przypadku możemy użyć kontenera IOC, możesz sam wybrać. W tym przykładzie użyję Autofaca (jest to jeden z najszybszych dostępnych). Możemy zachować odniesienie do tego w sekcji, Appaby było dostępne globalnie (niezbyt dobry pomysł, ale potrzebny do uproszczenia):

public class DependencyResolver
{
    static IContainer container;

    public DependencyResolver(params Module[] modules)
    {
        var builder = new ContainerBuilder();

        if (modules != null)
            foreach (var module in modules)
                builder.RegisterModule(module);

        container = builder.Build();
    }

    public T Resolve<T>() => container.Resolve<T>();
    public object Resolve(Type type) => container.Resolve(type);
}

public partial class App : Application
{
    public DependencyResolver DependencyResolver { get; }

    // Pass here platform specific dependencies
    public App(Module platformIocModule)
    {
        InitializeComponent();
        DependencyResolver = new DependencyResolver(platformIocModule, new IocModule());
        MainPage = new WelcomeView();
    }

    /* The rest of the code ... */
}

2. Będziemy potrzebować obiektu odpowiedzialnego za pobranie Page(View) dla konkretnego ViewModeli odwrotnie. Drugi przypadek może być przydatny w przypadku ustawienia strony głównej / głównej aplikacji. W tym celu powinniśmy zgodzić się na prostą konwencję, że wszystko ViewModelspowinno znajdować się w ViewModelskatalogu, a Pages(widoki) w Viewskatalogu. Innymi słowy, ViewModelspowinien żyć w [MyApp].ViewModelsprzestrzeni nazw i Pages(Widoki) w [MyApp].Viewsprzestrzeni nazw. Oprócz tego powinniśmy się zgodzić, że WelcomeView(Strona) powinna mieć a WelcomeViewModeli itp. Oto przykład kodu mappera:

public class TypeMapperService
{
    public Type MapViewModelToView(Type viewModelType)
    {
        var viewName = viewModelType.FullName.Replace("Model", string.Empty);
        var viewAssemblyName = GetTypeAssemblyName(viewModelType);
        var viewTypeName = GenerateTypeName("{0}, {1}", viewName, viewAssemblyName);
        return Type.GetType(viewTypeName);
    }

    public Type MapViewToViewModel(Type viewType)
    {
        var viewModelName = viewType.FullName.Replace(".Views.", ".ViewModels.");
        var viewModelAssemblyName = GetTypeAssemblyName(viewType);
        var viewTypeModelName = GenerateTypeName("{0}Model, {1}", viewModelName, viewModelAssemblyName);
        return Type.GetType(viewTypeModelName);
    }

    string GetTypeAssemblyName(Type type) => type.GetTypeInfo().Assembly.FullName;
    string GenerateTypeName(string format, string typeName, string assemblyName) =>
        string.Format(CultureInfo.InvariantCulture, format, typeName, assemblyName);
}

W przypadku ustawienia strony głównej będziemy potrzebować czegoś takiego ViewModelLocator, co ustawi BindingContextautomatycznie:

public static class ViewModelLocator
{
    public static readonly BindableProperty AutoWireViewModelProperty =
        BindableProperty.CreateAttached("AutoWireViewModel", typeof(bool), typeof(ViewModelLocator), default(bool), propertyChanged: OnAutoWireViewModelChanged);

    public static bool GetAutoWireViewModel(BindableObject bindable) =>
        (bool)bindable.GetValue(AutoWireViewModelProperty);

    public static void SetAutoWireViewModel(BindableObject bindable, bool value) =>
        bindable.SetValue(AutoWireViewModelProperty, value);

    static ITypeMapperService mapper = (Application.Current as App).DependencyResolver.Resolve<ITypeMapperService>();

    static void OnAutoWireViewModelChanged(BindableObject bindable, object oldValue, object newValue)
    {
        var view = bindable as Element;
        var viewType = view.GetType();
        var viewModelType = mapper.MapViewToViewModel(viewType);
        var viewModel =  (Application.Current as App).DependencyResolver.Resolve(viewModelType);
        view.BindingContext = viewModel;
    }
}

// Usage example
<?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:viewmodels="clr-namespace:MyApp.ViewModel"
    viewmodels:ViewModelLocator.AutoWireViewModel="true"
    x:Class="MyApp.Views.MyPage">
</ContentPage>

W końcu będziemy potrzebować podejścia, NavigationServicektóre będzie wspierać ViewModel First Navigation:

public class NavigationService
{
    TypeMapperService mapperService { get; }

    public NavigationService(TypeMapperService mapperService)
    {
        this.mapperService = mapperService;
    }

    protected Page CreatePage(Type viewModelType)
    {
        Type pageType = mapperService.MapViewModelToView(viewModelType);
        if (pageType == null)
        {
            throw new Exception($"Cannot locate page type for {viewModelType}");
        }

        return Activator.CreateInstance(pageType) as Page;
    }

    protected Page GetCurrentPage()
    {
        var mainPage = Application.Current.MainPage;

        if (mainPage is MasterDetailPage)
        {
            return ((MasterDetailPage)mainPage).Detail;
        }

        // TabbedPage : MultiPage<Page>
        // CarouselPage : MultiPage<ContentPage>
        if (mainPage is TabbedPage || mainPage is CarouselPage)
        {
            return ((MultiPage<Page>)mainPage).CurrentPage;
        }

        return mainPage;
    }

    public Task PushAsync(Page page, bool animated = true)
    {
        var navigationPage = Application.Current.MainPage as NavigationPage;
        return navigationPage.PushAsync(page, animated);
    }

    public Task PopAsync(bool animated = true)
    {
        var mainPage = Application.Current.MainPage as NavigationPage;
        return mainPage.Navigation.PopAsync(animated);
    }

    public Task PushModalAsync<TViewModel>(object parameter = null, bool animated = true) where TViewModel : BaseViewModel =>
        InternalPushModalAsync(typeof(TViewModel), animated, parameter);

    public Task PopModalAsync(bool animated = true)
    {
        var mainPage = GetCurrentPage();
        if (mainPage != null)
            return mainPage.Navigation.PopModalAsync(animated);

        throw new Exception("Current page is null.");
    }

    async Task InternalPushModalAsync(Type viewModelType, bool animated, object parameter)
    {
        var page = CreatePage(viewModelType);
        var currentNavigationPage = GetCurrentPage();

        if (currentNavigationPage != null)
        {
            await currentNavigationPage.Navigation.PushModalAsync(page, animated);
        }
        else
        {
            throw new Exception("Current page is null.");
        }

        await (page.BindingContext as BaseViewModel).InitializeAsync(parameter);
    }
}

Jak widać, istnieje BaseViewModel- abstrakcyjna klasa bazowa dla wszystkich, w ViewModelsktórych można zdefiniować metody, takie jak InitializeAsyncta, zostaną wykonane zaraz po nawigacji. A oto przykład nawigacji:

public class WelcomeViewModel : BaseViewModel
{
    public ICommand NewGameCmd { get; }
    public ICommand TopScoreCmd { get; }
    public ICommand AboutCmd { get; }

    public WelcomeViewModel(INavigationService navigation) : base(navigation)
    {
        NewGameCmd = new Command(async () => await Navigation.PushModalAsync<GameViewModel>());
        TopScoreCmd = new Command(async () => await navigation.PushModalAsync<TopScoreViewModel>());
        AboutCmd = new Command(async () => await navigation.PushModalAsync<AboutViewModel>());
    }
}

Jak rozumiesz, to podejście jest bardziej skomplikowane, trudniejsze do debugowania i może być mylące. Jednak jest wiele zalet, a w rzeczywistości nie musisz wdrażać go samodzielnie, ponieważ większość frameworków MVVM obsługuje go po wyjęciu z pudełka. Przykładowy kod pokazany tutaj jest dostępny na github .

Istnieje wiele dobrych artykułów na temat ViewModel First Navigationpodejścia, a także bezpłatny eBook wzorców aplikacji korporacyjnych wykorzystujący Xamarin.Forms, który szczegółowo wyjaśnia ten i wiele innych interesujących tematów.

EvZ
źródło
3

Za pomocą metody PushAsync () można wypychać i PopModalAsync () przesuwać strony do i ze stosu nawigacji. W moim przykładzie kodu poniżej mam stronę nawigacji (strona główna) i z tej strony wrzucam stronę z treścią, która jest stroną logowania, po ukończeniu strony logowania wskakuję z powrotem na stronę główną

~~~ Nawigacja może być traktowana jako ostatni na wejściu, pierwszy na stosie obiektów Page. Aby przejść z jednej strony do drugiej, aplikacja umieści nową stronę na tym stosie. Aby powrócić do poprzedniej strony, aplikacja zdejmie bieżącą stronę ze stosu. Ta nawigacja w Xamarin.Forms jest obsługiwana przez interfejs INavigation

Xamarin.Forms ma klasę NavigationPage, która implementuje ten interfejs i będzie zarządzać stosem Pages. Klasa NavigationPage doda również pasek nawigacyjny u góry ekranu, który wyświetla tytuł, a także będzie miał odpowiedni dla platformy przycisk Wstecz, który spowoduje powrót do poprzedniej strony. Poniższy kod pokazuje, jak zawijać NavigationPage wokół pierwszej strony w aplikacji:

Odniesienie do zawartości wymienionej powyżej i łącze, które należy przejrzeć, aby uzyskać więcej informacji na temat formularzy Xamarin, zobacz sekcję nawigacji:

http://developer.xamarin.com/guides/cross-platform/xamarin-forms/introduction-to-xamarin-forms/

~~~

public class MainActivity : AndroidActivity
{
    protected override void OnCreate(Bundle bundle)
    {
        base.OnCreate(bundle);

        Xamarin.Forms.Forms.Init(this, bundle);
        // Set our view from the "main" layout resource
        SetPage(BuildView());
    }

    static Page BuildView()
    {
        var mainNav = new NavigationPage(new RootPage());
        return mainNav;
    }
}


public class RootPage : ContentPage
{
    async void ShowLoginDialog()
    {
        var page = new LoginPage();

        await Navigation.PushModalAsync(page);
    }
}

// Usunięto kod dla uproszczenia, wyświetlany jest tylko pop

private async void AuthenticationResult(bool isValid)
{
    await navigation.PopModalAsync();
}
Chad Bonthuys
źródło
2

Jedna strona do innej nawigacji strony w Xamarin.forms przy użyciu właściwości Navigation Poniżej przykładowego kodu

void addClicked(object sender, EventArgs e)
        {
            //var createEmp = (Employee)BindingContext;
            Employee emp = new Employee();
            emp.Address = AddressEntry.Text;   
            App.Database.SaveItem(emp);
            this.Navigation.PushAsync(new EmployeeDetails());
  this.Navigation.PushModalAsync(new EmployeeDetails());
        }

Aby przejść z jednej strony do innej strony z widoczną komórką Poniżej kodu Xamrian.forms

 private async void BtnEdit_Clicked1(object sender, EventArgs e)
        {
            App.Database.GetItem(empid);
            await App.Current.MainPage.Navigation.PushModalAsync(new EmployeeRegistration(empid));
        }

Przykład jak poniżej

public class OptionsViewCell : ViewCell
    {
        int empid;
        Button btnEdit;
        public OptionsViewCell()
        {
        }
        protected override void OnBindingContextChanged()
        {
            base.OnBindingContextChanged();

            if (this.BindingContext == null)
                return;

            dynamic obj = BindingContext;
            empid = Convert.ToInt32(obj.Eid);
            var lblname = new Label
            {
                BackgroundColor = Color.Lime,
                Text = obj.Ename,
            };

            var lblAddress = new Label
            {
                BackgroundColor = Color.Yellow,
                Text = obj.Address,
            };

            var lblphonenumber = new Label
            {
                BackgroundColor = Color.Pink,
                Text = obj.phonenumber,
            };

            var lblemail = new Label
            {
                BackgroundColor = Color.Purple,
                Text = obj.email,
            };

            var lbleid = new Label
            {
                BackgroundColor = Color.Silver,
                Text = (empid).ToString(),
            };

             //var lbleid = new Label
            //{
            //    BackgroundColor = Color.Silver,
            //    // HorizontalOptions = LayoutOptions.CenterAndExpand
            //};
            //lbleid.SetBinding(Label.TextProperty, "Eid");
            Button btnDelete = new Button
            {
                BackgroundColor = Color.Gray,

                Text = "Delete",
                //WidthRequest = 15,
                //HeightRequest = 20,
                TextColor = Color.Red,
                HorizontalOptions = LayoutOptions.EndAndExpand,
            };
            btnDelete.Clicked += BtnDelete_Clicked;
            //btnDelete.PropertyChanged += BtnDelete_PropertyChanged;  

            btnEdit = new Button
            {
                BackgroundColor = Color.Gray,
                Text = "Edit",
                TextColor = Color.Green,
            };
            // lbleid.SetBinding(Label.TextProperty, "Eid");
            btnEdit.Clicked += BtnEdit_Clicked1; ;
            //btnEdit.Clicked += async (s, e) =>{
            //    await App.Current.MainPage.Navigation.PushModalAsync(new EmployeeRegistration());
            //};

            View = new StackLayout()
            {
                Orientation = StackOrientation.Horizontal,
                BackgroundColor = Color.White,
                Children = { lbleid, lblname, lblAddress, lblemail, lblphonenumber, btnDelete, btnEdit },
            };

        }

        private async void BtnEdit_Clicked1(object sender, EventArgs e)
        {
            App.Database.GetItem(empid);
            await App.Current.MainPage.Navigation.PushModalAsync(new EmployeeRegistration(empid));
        }



        private void BtnDelete_Clicked(object sender, EventArgs e)
        {
            // var eid = Convert.ToInt32(empid);
            // var item = (Xamarin.Forms.Button)sender;
            int eid = empid;
            App.Database.DeleteItem(empid);
        }

    }
Manohar
źródło
2

Połączenie:

((App)App.Current).ChangeScreen(new Map());

Utwórz tę metodę wewnątrz App.xaml.cs:

public void ChangeScreen(Page page)
{
     MainPage = page;
}
alansiqueira27
źródło
2
In App.Xaml.Cs:

MainPage = new NavigationPage( new YourPage());

Jeśli chcesz przejść z YourPage do następnej strony, wykonaj następujące czynności:

await Navigation.PushAsync(new YourSecondPage());

Możesz przeczytać więcej o nawigacji w Xamarin Forms tutaj: https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/navigation/hierarchical

Microsoft ma na ten temat całkiem niezłą dokumentację.

Istnieje również nowsza koncepcja Shell. Pozwala na nowy sposób strukturyzacji aplikacji i w niektórych przypadkach upraszcza nawigację.

Wprowadzenie: https://devblogs.microsoft.com/xamarin/shell-xamarin-forms-4-0-getting-started/

Film o podstawach Shell: https://www.youtube.com/watch?v=0y1bUAcOjZY&t=3112s

Dokumenty: https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/shell/

Jesper Baltzersen
źródło
0

Strona XAML dodaj to

<ContentPage.ToolbarItems>
            <ToolbarItem Text="Next" Order="Primary"
            Activated="Handle_Activated"/>

</ContentPage.ToolbarItems>   

na stronie CS

 async void Handle_Activated(object sender, System.EventArgs e)
        {
            await App.Navigator.PushAsync(new PAGE());
        }
Pxaml
źródło
0

Po PushAsyncużyciu PopAsync(z this), aby usunąć bieżącą stronę.

await Navigation.PushAsync(new YourSecondPage());
this.Navigation.PopAsync(this);
AliSafder
źródło
0

W Xamarinie mamy stronę o nazwie NavigationPage. Zawiera stos ContentPages. NavigationPage ma metodę taką jak PushAsync () i PopAsync (). PushAsync dodaje stronę na górze stosu, w tym czasie ta strona stanie się aktualnie aktywną stroną. Metoda PopAsync () usuwa stronę z góry stosu.

W App.Xaml.Cs możemy ustawić np.

MainPage = new NavigationPage (new YourPage ());

await Navigation.PushAsync (new newPage ()); ta metoda doda newPage na szczycie stosu. W tym momencie nePage będzie aktualnie aktywną stroną.

PRASAD CP
źródło