通过媒体资源控制活动视图

时间:2019-06-26 20:36:49

标签: c# wpf xamarin mvvm

我建立了一个兼容mvvm的可正常使用的wpf应用程序。我有一个窗口,在其中我通过一个属性(名为CurrentHomeView的公共对象)进行控制,该属性将显示Datatemplate。例如:如果我的属性等于LoginViewModel,则窗口将显示LoginControl,它是一个UserControl。到目前为止,一切都很好。 现在,我想使用此系统并在xamarin应用程序中使用它。但是我在wpf应用程序中实现它的方式似乎不是xamarin中正确的方法。

我该怎么办,它将以相同的方式工作?

提前坦克;)

您将在我的代码中,到目前为止我已经建立的。我的ContantPage没有更改contant: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中的Page,应该使用相同的Class来映射活动视图:

<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 :(得分:0)

Xamarin.Forms中没有等效于WPF ContentControl的文件。您可以按照建议的here创建自定义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);
        }
    }
}

也不支持隐式数据模板。您可以按照建议的converter使用here来解决此问题。

答案 1 :(得分:0)

据我了解,您想在Xamarin应用程序中从WPF应用程序重用ViewModels-这是可行的,但并不容易。

您在WPF中进行视图切换的方式是可行的,并且可以,但是当您要使用多平台时,并不是“如何完成”。

您应该做的第一件事是确保ViewModels与平台无关-将它们全部放入PCL中。正确的MVVM应用程序即使没有附加任何视图也应该能够运行并执行操作-这包括切换活动的ViewModel。

您可以通过使用导航/路由服务来实现这一点-大多数MVVM框架都具有该功能。基本上,您需要显示一些ViewModel -如果您想学习很多东西,编写自己的东西,否则要使用现有的东西,再浪费一次的时间是不值得的。 VM的显示方式取决于程序在哪个平台上运行-从VM的角度来看应该没有什么区别。尽管如此,您仍需要为每个平台使用单独的视图(WPF中的用户控件,表单中的页面)。

我认为最好的MVVM框架之一是ReactiveUI,它是用Xamarin编写的,因此速度快,启动时间短等。它也可用于大多数平台:WPF,WinForms,Windows Universal Apps,甚至还有Avalonia和其他一些。 RxUI甚至支持开箱即用的视图激活,这非常方便。另外,一旦您做出反应,就无法退回:)

This文章介绍了路由概念的基础。

从那里快乐地挖掘:)