Как структура классов модели представления, модели и куда девать расчета/общей свойства
Первоначально, когда я впервые задал этот вопрос, он был указан как слишком длинный. Признаюсь, он охватывает пару связанных вопросов. Я борюсь с общей структурой приложения и с тем, где найти свойства.
Я работаю с приложениями C# и WinForms уже более 5 лет и решил начать изучать WPF и MVVM для нового проекта. Это оказалось полезным, однако, похоже, люди разрываются в нескольких направлениях из-за некоторых концепций, что затрудняет исследование и поиск хорошего направления.
Должен отметить, что я делаю это в C# 6.0, .NET 4.5.2 и без использования фреймворков, таких как Prism или MvvmLight. Я бы предпочел сначала изучить основы, прежде чем применять какую-то магию.
Я опишу свой проект, чтобы проиллюстрировать вопросы.
Приложение, которое я создаю, позволяет просматривать только заявки в службу технической поддержки из базы данных SQL2000. Я только запрашиваю базу данных, но никогда не пишу в нее (для этого у нас есть отдельное приложение). У меня нет контроля над базой данных, и я не могу повлиять на переход на что-то новое. Кроме того, некоторые таблицы не очень нормализованы; дублирование данных и т. д. К сожалению, я не могу использовать Entity Framework без особых усилий. Я запрашиваю базу данных и заполняю свои настраиваемые объекты. Хотя в базе данных много таблиц, я использую четыре основных: Ticket, Event, Escalation и Rma. Таблица Ticket имеет отношение «один ко многим» с таблицами Event, Escalation и Rma; где один билет может относиться к нулю или более событиям, эскалациям или RMA. Я запрашиваю в базе данных набор билетов. Когда пользователь выбирает конкретный билет из списка, он запрашивает в базе данных остальную информацию о заявке, чтобы я мог заполнить события, эскалации и RMA.
Просмотры:
MainWindow.xaml
(Окно) - Меню, TicketsView, Строка СостоянияTicketsView.xaml
(UserControl) - TicketsGroupBox (текст привязан к TicketCollectionName), TicketsDataGrid, TicketViewTicketView.xaml
(UserControl) - TicketGroupBox, EventsGroupBox, EventsDataGrid, EscalationsGroupBox, EscalationsDataGrid, RmasGroupBox, RmasDataGridПросмотр моделей:
MainWindowViewModel
– TicketsViewModel, TicketsRepository, команды меню, StatusTextTicketsViewModel
- TicketsRepository (передается в конструктор при создании), TicketCollectionName, ObservableCollection< Ticket>, SelectedTicket (создает TicketViewModel из объекта Ticket, переданного TicketsView.TicketsDataGrid.Элемент)TicketViewModel
– , Коллекция ObservableCollection&ЛТ авиабилет;событие&ГТ;, коллекция ObservableCollection&ЛТ;эскалации&ГТ;, коллекция ObservableCollection&ЛТ;Иов&ГТ;Модели:
Ticket
- Свойства таблицы билетов, список & lt;событие>, Список & lt;эскалация>, Список< Rma>Event
- Свойства таблицы событийEscalation
- Свойства эскалацииRma
- Свойства таблицы RmaДополнительный:
TicketRepository
класс-взаимодействует с базой данных, заполняя список объектов тикетов.Надеюсь, вышеизложенное дает представление о взаимоотношениях между объектами MVVM, приблизительное представление о структуре приложения.
Первая проблема, с которой я столкнулся, заключается в том, что мне нужно, чтобы свойства расчета/сводки/итога были представлены в сетках данных. Можно было бы подумать, что вы должны просто включить эти свойства В модель, однако более популярное мнение, которое я читал, состоит в том, чтобы никогда не включать эту логику в модель. Многие люди помещают их в ViewModels, что может иметь смысл. Итак, вместо того, чтобы иметь
TicketsViewModel.ObservableCollection<Ticket>
- Я бы так и сделал. TicketsViewModel.ObservableCollection<TicketViewModel>
. В любое время SelectedItem
изменившись, я бы уже имел TicketViewModel
готов к работе; и не нужно будет его создавать. Сложность здесь заключается в том, что если мне нужны свойства calculation/summary/total в других трех сетках данных, которые не имеют отдельного представления/UserControls, т. е. EventsDataGrid
, EscalationsDataGrid
, и RmasDataGrid
? Я все еще создаю их в ViewModels; или я создаю их в каком-то другом классе-оболочке для модели?Если я следую логике выше, то структура, кажется, быстро усложняется; приходится поддерживать отдельную иерархию объектов Model и ViewModel. Если это правильный подход, то я не уверен, где вещи должны быть и когда/где я их загружу. Мне кажется, что я бы дублировал усилия, но не вижу, как еще это сделать, если мне нужны эти свойства расчета/итога. Означает ли это, что мне нужно создавать ViewModel каждый раз, когда они мне нужны? Или я иду по неверному пути?
Спасибо за любое руководство; я был бы очень признателен.
Что я уже пробовал:
Я попробовал структуру, описанную выше, но затем начал создавать ViewModels, как я обсуждаю ближе к концу.
J. Calhoun
Это трудно устранить, потому что я не вижу, как вы используете эти вещи, поэтому я не уверен в контексте вычисления, но, судя по тому, что вы помещаете эти свойства в модель представления, я предполагаю, что summary/total-это что-то вроде summary или total всей коллекции RMA/эскалаций/событий.
Кроме того, находятся ли эти сетки в отдельных представлениях? Итак, вы говорите, что в каждой модели представления вам понадобится что-то вроде Calculation {get; set;}
Способ, которым вы можете отслеживать все это, - это модель наблюдателя, которую Сунил Кумар объясняет здесь Шаблон наблюдателя в .NET[^] также Ислам Элдемери имеет хорошую реализацию Шаблоны Проектирования - Шаблон Наблюдателя[^] Таким образом, каждая модель представления, которая должна знать о событии OnChanged, может просто зарегистрироваться на это событие, чтобы все они обновились при необходимости.
Еще одна вещь, которую я не понимаю, - это билеты.модель представления.ObservableCollection & lt;ticketsviewmodel & gt; Таким образом, у вас есть несколько экземпляров одной и той же модели представления? Разве это не разрушает ваши оковы? Там должно быть только 1 TicketsViewModel, поэтому не должно быть коллекции.
bnmc
Спасибо за ответ, Джей Калхун; должно быть, я его пропустил.
Я думаю, что нашел хорошее направление для движения, благодаря ответам на мой другой опубликованный вопрос. Основной вопрос здесь заключается в том, должен ли я включать свойства вычисления в объекты модели или оболочку для этих объектов модели, например ViewModel.
Я решил привязываться только напрямую к ViewModels, поэтому я создаю только расчетные свойства в ViewModels. Но поскольку ViewModel действует как оболочка, и я хочу включить итоги в DataGrid в View, мне нужно иметь ObservableCollections таких вещей, как TicketsViewModel.ObservableCollection
Я снова взгляну на паттерн наблюдателя, так как думаю, что он может немного облегчить другие вещи.