Как связать модель представления с представлением в XAML в Xamarin? - PullRequest
0 голосов
/ 30 сентября 2019

У меня очень простое представление.

<ContentPage x:Class="ThetaRex.InvestmentManager.Merlin.Views.ScenarioSelectionPage"
             Title="{Binding Title}"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns="http://xamarin.com/schemas/2014/forms">
    <StackLayout>
        <ListView ItemsSource="{Binding Items}"/>
    </StackLayout>
<ContentPage/>

Код также очень прост:

namespace ThetaRex.InvestmentManager.Merlin.Views
{
    using System.ComponentModel;
    using ThetaRex.InvestmentManager.Merlin.ViewModels;
    using Xamarin.Forms;

    public partial class ScenarioSelectionPage : ContentPage
    {
        public ScenarioSelectionPage()
        {
            InitializeComponent();
            this.BindingContext = this.ViewModel = new ScenarioSelectionViewModel();
        }

        public ScenarioSelectionViewModel ViewModel { get; set; }

        protected override void OnAppearing()
        {
            base.OnAppearing();
            ViewModel.LoadItemsCommand.Execute(null);
        }
    }
}

Исходя из чистой среды MVVM в WPF и UWP, яхотите связать представление с моделью представления в XAML, не используя this.Binding = ViewModel в коде позади. Я пробовал:

<ContentPage x:Class="ThetaRex.InvestmentManager.Merlin.Views.ScenarioSelectionPage"
             xmlns:controls="clr-namespace:ThetaRex.InvestmentManager.Merlin.Controls"
             BindingContext="{Binding ViewModel}"
             Title="{Binding Title}"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns="http://xamarin.com/schemas/2014/forms">

Но это не сработало. Как связать ViewModel из XAML?

Примечание: Я знаю, что могу создать модель представления с нуля в XAML, но она не использует тот же экземпляр, что и кодсзади в представлении использует, так что это не вариант.

1 Ответ

0 голосов
/ 30 сентября 2019

Если я понял, что вы хотите, решение состоит в том, чтобы создать ViewModelLocator следующим образом:

1. ViewModelLocalizator Class

 public static class ViewModelLocalizator
    {

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

        public static bool GetAutoWireViewModel(BindableObject bindable)
        {
            return (bool)bindable.GetValue(AutoWireViewModelProperty);
        }

        public static void SetAutoWireViewModel(BindableObject bindable, bool value)
        {
            bindable.SetValue(AutoWireViewModelProperty, value);
        }


        /// <summary>
        /// VERIFY THE VIEW NAME AND ASSOCIATE IT WITH THE VIEW MODEL OF THE SAME NAME. REPLACING THE 'View' sufix WITH THE 'ViewModel'
        /// </summary>
        private static void OnAutoWireViewModelChanged(BindableObject bindable, object oldValue, object newValue)
        {
            if (!(bindable is Element view))
            {
                return;
            }

            var viewType = view.GetType();

            var viewModelName = viewType.FullName.Replace(".Views.", ".ViewModels.").Replace("Page", "ViewModel");


            var viewModelType = Type.GetType(viewModelName);

            if (viewModelType == null) { return; }

                var vmInstance = Activator.CreateInstance(viewModelType);
                if (vmInstance != null)
                {
                    view.BindingContext = vmInstance;
                }

        }


    }

2. Использование его в вашем представлении

<ContentPage x:Class="YourProject.Views.YourTestPage"
             Title="{Binding Title}"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:viewModelBase="clr-namespace:YourProject.ViewModels;assembly=YouProject"
             viewModelBase:ViewModelLocalizator.AutoWireViewModel="true"
>
    <StackLayout>
        <ListView ItemsSource="{Binding Items}"/>
    </StackLayout>
<ContentPage/>


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