Можно ли автоматически регистрировать ViewModels и Views вместе на App.xaml.cs - PullRequest
0 голосов
/ 07 августа 2020

Можно ли автоматически зарегистрировать модель представления с представлением без библиотеки классов, такой как Prism, в методе OnStartUp из App.xaml.cs

У меня есть что-то подобное в моем предыдущем проекте Prism Xamarin на запуск приложения.

protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
    //Registered Navigation Containers
    containerRegistry.RegisterForNavigation<LoginPage>("Login");
    containerRegistry.RegisterForNavigation<RegisterPage>("Register");
    containerRegistry.RegisterForNavigation<ProfilePage>("Profile");
    containerRegistry.RegisterForNavigation<CreateAppointmentPage>("CreateAppointment");
    containerRegistry.RegisterForNavigation<NotificationPage>("Notification");
    //Dependency Services
    containerRegistry.RegisterSingleton<IConnectivityService, ConnectivityService>();
    containerRegistry.RegisterSingleton<IAuthenticationService, AuthenticationService>();
    containerRegistry.RegisterSingleton<IAppAPIService, AppAPIService>();
    containerRegistry.RegisterSingleton<IPushNotificationManager, PushNotificationManager>();
}

Моя нынешняя компания не хочет использовать библиотеки. Моя цель - иметь чистый код программной части для всех представлений. Я бы хотел избежать чего-то вроде кода программной части:

public MainWindow()
{
     InitializeComponent();
     DataContext = new MainWindowViewModel();
}

Надеюсь, мой вопрос ясен. Спасибо.

Ответы [ 2 ]

1 голос
/ 07 августа 2020

Нет ничего автоматического c в рамках net.

Вы можете смягчить проблему, используя сначала модель просмотра и таблицы данных. Вот как я обычно работаю в приложении с одним окном.

У меня есть словарь ресурсов, объединенный в app.xaml, который связывает пользовательский элемент управления с моделью просмотра по типу.

Вы можете увидеть Здесь используется самая базовая c версия:

https://social.technet.microsoft.com/wiki/contents/articles/52485.wpf-tips-and-tricks-using-contentcontrol-instead-of-frame-and-page-for-navigation.aspx

<DataTemplate DataType="{x:Type local:LoginViewModel}">
    <local:LoginView/>
</DataTemplate>

Навигация осуществляется путем установки свойства CurrentView в mainwindowviewmodel для экземпляра модели просмотра. Это связано с содержимым элемента управления содержимым в MainWindow. Табличка данных затем создаст шаблон для соответствующего пользовательского элемента управления.

Никакие навигационные сервисы и модели просмотра, которые должны быть одиночными, не могут быть кэшированы в объектах, экземплярах mainwindowviewmodel.

Тогда у вас будет «только» mainwindowviewmodel. У ручного создания экземпляра mainwindowviewmodel есть свои плюсы. Таким образом, вы можете контролировать, когда происходит создание дорогостоящего экземпляра. Не все это делается автоматически, поскольку эта модель просмотра требует множества сервисов через ее ctor.

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

Конечно, вы могли бы написать что-нибудь.

Дело в том, что вы, вероятно, собираетесь переписывать код, который очень похоже на то, что кто-то уже написал. Но поскольку у вас, скорее всего, нет 6 месяцев, выделенных для работы по замене фреймворка, ваша версия, вероятно, будет намного проще.

Caliburn micro использует соглашения об именах для связывания моделей и представлений. Вы могли бы написать что-то подобное и использовать отражение.

Или, может быть, вы могли бы go вернуться к своему боссу и обсудить его проблему. Лично я не фанат Prism из-за ее сложности. Может быть, у него такая проблема. Может быть, более приемлемый фреймворк вроде mvvmlight будет более приемлемым.

1 голос
/ 07 августа 2020

Нет, встроенной функции для этого в WPF нет. Для этого нужны библиотеки, такие как Prism, поэтому вам не нужно изобретать велосипед. В фоновом режиме Prism использует несколько механизмов для достижения этой цели.

  • Контейнер внедрения зависимостей для регистрации и разрешения типов
  • Устанавливает отслеживание того, какое представление принадлежит какой модели представления
  • Обнаружение моделей представления посредством соглашений об отражении и именовании
  • Присоединенное свойство для автоматического назначения модели представления представлению.
  • ...

В зависимости от ваши требования вам придется написать части этого самостоятельно или использовать альтернативные концепции, которые являются более легкими, такие как тип реестра представления и фабрика для их создания, например:

public interface IViewRegistry
{
   void Register<TView, TViewModel>()
      where TView : FrameworkElement
      where TViewModel : INotifyPropertyChanged;

   Type GetViewModelType<TView>()
         where TView : FrameworkElement;
}

public interface IViewFactory
{
   TView Create<TView>()
      where TView : FrameworkElement;
}

Реальная реализация реестра представлений будет есть словарь для отслеживания сопоставления между представлениями и моделями представлений, которое может быть предоставлено GetViewModelType. Ограничение типа FrameworkElement гарантирует, что вы можете установить DataContext.

public class ViewRegistry : IViewRegistry
{
   private Dictionary<Type, Type> _mappings;

   public ViewRegistry()
   {
      _mappings = new Dictionary<Type, Type>();
   }

   public void Register<TView, TViewModel>()
      where TView : FrameworkElement
      where TViewModel : INotifyPropertyChanged
   {
      _mappings.Add(typeof(TView), typeof(TViewModel));
   }

   public Type GetViewModelType<TView>()
      where TView : FrameworkElement
   {
      return _mappings.ContainsKey(typeof(TView)) ? _mappings[typeof(TView)] : null;
   }
}

Фабрика создаст новые экземпляры представления и его модель представления с использованием отражения или через контейнер внедрения зависимостей и присвойте DataContext. Я действительно рекомендую вам использовать контейнер зависимостей, потому что ваши модели представления могут иметь множество зависимостей, и вам придется решать или создавать их самостоятельно. См. Комментарий @ BionicCode по этому поводу.

public class ViewFactory : IViewFactory
{
   private readonly IViewRegistry _viewRegistry;

   public ViewFactory(IViewRegistry viewRegistry)
   {
      _viewRegistry = viewRegistry;
   }

   public TView Create<TView>() where TView : FrameworkElement
   {
      var viewModelType = _viewRegistry.GetViewModelType<TView>();
      var view = // ...resolve the view via dependency injection or create it via reflection using its type
      var viewModel =  // ...resolve the view model via dependency injection or create it via reflection using its type

      view.DataContext = viewModel;
      return view;
   }
}

В вашем приложении процесс регистрации разрешающих представлений теперь похож на Prism.

var viewRegistry = new ViewRegistry();
var viewFactory = new ViewFactory(viewRegistry);

viewRegistry.Register<MainWindow, MainWindowViewModel>();
var mainWindow = viewFactory.Create<MainWindow>();
...