Управление активным видом через свойство - PullRequest
0 голосов
/ 26 июня 2019

Я создал хорошее работающее wpf-приложение, совместимое с mvvm. У меня есть одно окно, в котором я контролирую через свойство (публичный объект с именем CurrentHomeView), который будет показан Dateatemplate. Например: если мое свойство равно LoginViewModel, в окне отобразится LoginControl, который является UserControl. Все идет нормально. Теперь я хочу взять эту систему и использовать ее в приложении xamarin. Но способ, которым я сделал это в своем wpf-приложении, кажется не правильным в xamarin.

Что мне нужно сделать, чтобы это работало так же?

Танки заранее;)

Вы будете в моем коде, что я построил до сих пор. Моя ContantPage не меняет константу: D

Мой класс для управления стоимостью моей собственности:

namespace Core.ApplicationStartUp
{
    public class StartUp : BindableBase
    {
        LoginViewModel _loginViewModel;

        private bool _isNewUser;
        private object _currentMainView;

        public object CurrentMainView
        {
            get => _currentMainView;
            set => SetProperty(ref _currentMainView, value);
        }

        public bool IsNewUser
        {
            get => _isNewUser;
            set => SetProperty(ref _isNewUser, value);
        }

        public StartUp()
        {
            _isNewUser = SearchUserData();
            if (!IsNewUser)
                LoadLoginControl();
        }

        private bool SearchUserData()
        {
            return false;
        }

        private void LoadLoginControl()
        {
            _loginViewModel = new LoginViewModel(this);
            bool isIn = _loginViewModel.CheckStatus();
            if (!isIn)
                CurrentMainView = _loginViewModel;
            else
                _loginViewModel.Login();
        }
    }
}

Мое окно в приложении WPF:

<Window.Resources>
        <DataTemplate DataType="{x:Type loginCore:LoginViewModel}">
            <loginControl:LoginControl/>
        </DataTemplate>
        <DataTemplate DataType="{x:Type registrationCore:RegistrationViewModel}">
            <registrationControl:RegistrationControl/>
        </DataTemplate>
        <DataTemplate DataType="{x:Type navigationCore:NavigationViewModel}">
            <navigationControl:NavigationControl/>
        </DataTemplate>
    </Window.Resources>

    <Border BorderThickness="0.5" BorderBrush="White">
        <DockPanel LastChildFill="True">
            <ContentControl Content="{Binding CurrentMainView, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
        </DockPanel>
    </Border>

А это моя страница в Xamarin, которая должна использовать тот же класс для магии активного вида:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             xmlns:navigationControl="clr-namespace:Mobile.Areas.Navigation"
             xmlns:navigationCore="clr-namespace:Core.Areas.Navigation;assembly=Core"
             xmlns:registrationCore="clr-namespace:Core.Areas.Registration;assembly=Core"
             xmlns:registrationControl="clr-namespace:Mobile.Areas.Registration"
             xmlns:loginCore="clr-namespace:Core.Areas.Login;assembly=Core"
             xmlns:loginControl="clr-namespace:Mobile.Areas.Login"
             x:Class="Mobile.MainWindow">

    <ContentPage.Resources>
        <DataTemplate x:DataType="{x:Type loginCore:LoginViewModel}"
                      x:Key="LoginControl">
            <loginControl:LoginControl/>
        </DataTemplate>
        <DataTemplate x:DataType="{x:Type registrationCore:RegistrationViewModel}"
                      x:Key="RegistrationControl">
            <registrationControl:RegistrationControl/>
        </DataTemplate>
        <DataTemplate x:DataType="{x:Type navigationCore:NavigationViewModel}"
                      x:Key="NavigationControl">
            <navigationControl:NavigationControl/>
        </DataTemplate>
    </ContentPage.Resources>

    <StackLayout>
        <ContentView Content="{Binding CurrentMainView}"/>
    </StackLayout>

</ContentPage>

Я не получаю никаких исключений или ошибок. Далее больше нет информации в выводе.

Ответы [ 2 ]

0 голосов
/ 27 июня 2019

Как я понимаю, вы хотите повторно использовать ваши ViewModels из приложения WPF в приложении Xamarin - это выполнимо, но не просто.

То, как вы делали просмотр переключения в WPF, работает и работает нормально, но это не "как это делается", когда вы хотите перейти на мультиплатформу.

Первое, что вы должны сделать, это сделатьУбедитесь, что ViewModels не зависят от платформы - поместите их все в PCL.Правильное приложение MVVM должно быть в состоянии запускать и выполнять какие-либо действия даже без каких-либо подключенных представлений - это включает переключение активной ViewModel.

Это достигается с помощью службы навигации / маршрутизации - в большинстве сред MVVM это есть.По сути, это то, что вы просите показать некоторую ViewModel - если вы хотите многому научиться, напишите свое собственное, в противном случае используйте существующее, не стоит тратить время на его придумывание еще раз.То, как отображается виртуальная машина, зависит от того, на какой платформе запущена программа - однако с точки зрения виртуальной машины не должно быть никаких отличий.Тем не менее, вам понадобятся отдельные представления (UserControls в WPF, страницы в формах) для каждой платформы.

Одна из лучших на мой взгляд сред MVVM - ReactiveUI , написанная с учетом Xamarin,поэтому он быстрый, имеет малое время запуска и т. д. Он также работает с большинством платформ: WPF, WinForms, Windows Universal Apps, даже Avalonia и некоторыми другими.RxUI даже поддерживает активацию представлений из коробки, что более чем удобно.Кроме того, как только вы начнете реагировать, пути назад уже не будет:)

В этой статье изложены основы концепции маршрутизации.

Удачной копки оттуда:)

0 голосов
/ 27 июня 2019

В Xamarin.Forms нет эквивалента WPF ContentControl.Вы можете создать пользовательский ContentView как предложено здесь :

public class ContentPresenter : ContentView
{
    public static readonly BindableProperty ItemTemplateProperty = BindableProperty.Create("ItemTemplate", typeof(DataTemplate), typeof(ContentPresenter), null, propertyChanged: OnItemTemplateChanged);

    private static void OnItemTemplateChanged(BindableObject bindable, object oldvalue, object newvalue)
    {
        var cp = (ContentPresenter)bindable;

        var template = cp.ItemTemplate;
        if (template != null)
        {
            var content = (View)template.CreateContent();
            cp.Content = content;
        }
        else
        {
            cp.Content = null;
        }
    }

    public DataTemplate ItemTemplate
    {
        get
        {
            return (DataTemplate)GetValue(ItemTemplateProperty);
        }
        set
        {
            SetValue(ItemTemplateProperty, value);
        }
    }
}

Также не поддерживается неявные шаблоны данных.Вы можете обойти это, используя конвертер , как предложено здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...