Как добавить ViewModel для новых страниц приложений Xamarin Native для iOS и Android - PullRequest
0 голосов
/ 19 июня 2019

Контекст : мне передали это огромное корпоративное приложение для iOS и Android Xamarin, которое не использует ViewModels или какую-либо инфраструктуру MVVM.Он имеет отдельный слой сетевых сервисов и имеет много страниц, поэтому начинать заново не имеет никакого смысла.

Зачем нужно изменение : MVVM отсутствует, сервисный уровень вызывается непосредственно из классов пользовательского интерфейса (Fragments & ViewControllers), и нет хорошей абстракции.Поэтому я начну с 1 представления, а затем создаю TechDebt для преобразования остальной части приложения.

Что я знаю :

  1. Для добавления сред MVVM требуется создание обширнойизменения, особенно для использования навигационных сервисов для навигации по представлениям, и лучше всего делать, если они добавлены, когда приложение отображается зеленым цветом.
  2. Как видно здесь , в Android есть простой способ использования ViewModel, но тогда я не смогу использовать его для iOS.
  3. Я также знаю, что могу вместо этого запустить страницу форм Xamarin, и она будет готова для MVVM, поскольку я могу просто назначить свойство BindingContext экземпляру ViewModel.

Что мне нужно : мне нужно создать одну новую страницу для iOS и одну для Android.Я хочу иметь возможность создавать ViewModel, который используется для iOS и Android.Я хочу иметь возможность использовать его для отдельного представления, которое я создаю, и его следует инициализировать при загрузке страницы.

Как добавить 1 модель представления, которая является общей для ViewController & Fragment?Я что-то упускаю, это намного легче, чем я делаю это?

Ответы [ 2 ]

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

Закончилась возможность использовать MvvmLight для этого. Добавил пакет Nuget в проекты, создал ViewModelBase в проекте Core Shared Library:

public abstract class ViewModelBase : GalaSoft.MvvmLight.ViewModelBase
{
        private PropertyChangedEventHandler propertyChangedEventHandler;

        protected bool IsLoading { get; set; }

        public bool RegisteredPropertyEventHandler { get; set; }

        public const string ErrorMessagePropertyName = "ErrorMessage";

        public string ErrorMessage { get; set; }

        public string SuccessMessage { get; set; }

        public void RegisterPropertyEventHandler(PropertyChangedEventHandler propertyChangedEventHandler)
        {
            this.propertyChangedEventHandler = propertyChangedEventHandler;
            this.PropertyChanged += propertyChangedEventHandler;
            this.RegisteredPropertyEventHandler = true;
        }

        public void UnegisterPropertyEventHandler()
        {
            if (this.RegisteredPropertyEventHandler)
            {
                this.PropertyChanged -= propertyChangedEventHandler;
                this.RegisteredPropertyEventHandler = false;
                this.propertyChangedEventHandler = null;
            }
        }

        public void TearDown()
        {
            this.UnegisterPropertyEventHandler();
        }

        protected void NotifyError (string message)
        {
            this.ErrorMessage = message;
            RaisePropertyChanged (() => ErrorMessage);
        }
}

и ViewModelLocator

public class ViewModelLocator
{
        public const string ABCPageKey = "ABCPage";

        public ABCViewModel ABC 
        {
            get 
            {
                return ServiceLocator.Current.GetInstance<ABCViewModel> ();
            }
        }

        public ViewModelLocator ()
        {
            ServiceLocator.SetLocatorProvider (() => SimpleIoc.Default);

            // Register all of the view models
            SimpleIoc.Default.Register<ABCViewModel> ();
        }

        public static void Cleanup ()
        {
        }

        public T GetViewModel<T> ()
        {
            return ServiceLocator.Current.GetInstance<T> ();
        }
}

На iOS у меня уже был BaseUIViewController, поэтому поверх него я создал BaseViewModelUIViewController

public abstract partial class BaseViewModelUIViewController<T> : BaseUIViewController where T : ViewModelBase
    {
        public T ViewModel 
        {
            get 
            {
                return App.Locator.GetViewModel<T> ();
            }
        }

        public BaseViewModelUIViewController (IntPtr handle) : base (handle)
        {
        }

        internal virtual void ViewModelPropertyChangedHandler (object sender, PropertyChangedEventArgs e)
        {
            Console.WriteLine (string.Format ("****** Property Changed for {0} in {1}", e.PropertyName, this.GetType ().Name));
            switch (e.PropertyName) 
            {
            default:
                break;
            }
        }
}

А потом Android, аналогично, у меня уже был BaseFragment, поэтому я создал BaseViewModelFragment поверх него

public class BaseViewModelFragment<T> : BaseFragment where T : ViewModelBase
{
        public T ViewModel 
        {
            get 
            {
                return App.Locator.GetViewModel<T> ();
            }
        }

        public BaseViewModelFragment (string title) : base (title)
        {
        }

        internal virtual void ViewModelPropertyChangedHandler (object sender, PropertyChangedEventArgs e)
        {
            Console.WriteLine (string.Format ("****** Property Changed for {0} in {1}", e.PropertyName, this.GetType ().Name));
            switch (e.PropertyName) 
            {
            default:
                break;
            }
        }

        public override void OnDestroyView ()
        {
            this.ViewModel.TearDown ();

            base.OnDestroyView ();
        }
}

Я надеюсь, что это имеет смысл для других людей, которые ищут решения.

Создание ViewModels: Естественно, для каждого нового созданного ViewModel мне приходилось регистрировать его в ViewModelLocator.

Использование ViewModels: с точки зрения использования вы можете просто использовать ViewModel в пользовательском интерфейсе, наследуя от ": BaseViewModelUIViewController" для iOS или от ": BaseViewModelFragment" для Android

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

К сожалению, вы ничего не пропустили, все ваши требования верны, и вы правильно перечислили различные направления, которые вы можете предпринять (и которые вам не нравятся).

Xamarin.Android и Xamarin.iOS созданы не с учетом привязки данных, а с использованием собственных интерфейсов, только Xamarin.Forms созданы для привязки данных. Возможности нативных платформ для использования привязки данных ограничены (если бы она существовала, она была бы несовместима между платформами, и вам пришлось бы создавать отдельные модели представлений, а привязка данных для iOS на данный момент отсутствует в любом случае).

Таким образом, в Xamarin.iOS и Xamarin.Android отсутствует привязка данных. Вы полностью должны абстрагироваться от общей бизнес-модели и связать ее с пользовательским интерфейсом.

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