У нас есть приложение Silverlight. В нем есть несколько страниц, которые находятся внутри вкладок в нашем интерфейсе. Раньше мы называли их SavePage и PanelPage. Сохранить страницу имеет только базовые функции для редактирования деталей записи, создания новых записей и удаления существующей записи на экране. PanelPage наследуется от SavePage. PanelPage немного сложнее в том, что панели становятся видимыми/невидимыми, основываясь на выборе, который вы делаете на экране.Какой шаблон дизайна у меня закончился?
Код был огромным беспорядком в приложении Silverlight. Но недавно я сделал шаг портирования этого кода для работы в Xamarin Forms. Я сделал две неудачные попытки сделать это, и с моей третьей попытки я получил код для работы на всех целевых платформах: Silverlight, iOS, Android и Windows UWP. На данный момент я доволен дизайном класса. Это может быть проще, но это поможет сделать какое-то время.
Целью этого дизайна является то, что логика пользовательского интерфейса абстрагируется от физических элементов управления пользовательского интерфейса. Я удалил использование System.Windows от общего кода, который находится на обеих платформах (SavePage и PanelPage). Эти страницы больше похожи на «Контроллеры» в шаблонах MVC или MVVC. Но я не думаю, что то, что я создал, - это точно один из этих двух шаблонов. Тем не менее, мне пришлось разделить эти классы на две части: одну для абстрактных пользовательских интерфейсов, таких как SaveAsync(), и одну для специфичных для платформы UI-вызовов, таких как ReportError. Я изо всех сил пытаюсь получить название классов правильно, так как я даже не знаю, какой шаблон дизайна я использую.
Вот диаграмма классов: Вот код для некоторых из интерфейсов заинтересованных:
public interface IPage : IRecordSelector
{
/// <summary>
/// This event should be raised when the busy state of a tab changes
/// </summary>
event EventHandler<BusyStateChangedEventArgs> BusyStateChanged;
object PageElement { get; }
}
public interface IButtonDrivenPage : IPage
{
Task SaveClickAsync();
Task DuplicateClickAsync();
Task DeleteClickAsync();
Task NewClickAsync();
event EventHandler<ButtonVisibilityChangedEventArgs> ButtonVisibilityChanged;
IRecord GetRecord();
}
public interface ISavePage : IButtonDrivenPage, IRequestClose
{
string DataContextXmlSnapshot { get; }
bool PromptForChangeCancel { get; }
IRecord SelectedItem { get; }
Task SetSelectedItemAsync(IRecord selectedItem);
event EventHandler SelectedItemChanged;
void Close();
void SetAutomationObject(object automationObject);
ISavePageUIController SavePageUIController { get; }
}
public interface ISavePageUIController: IDisposable
{
/// <summary>
/// The UI controller is notifying the page that the UI content has been loaded
/// </summary>
event EventHandler ContentLoaded;
/// <summary>
/// Prompt the user for a yet or a no
/// </summary>
Task<bool> GetYesNoFromPrompt(string message, string title);
/// <summary>
/// Report an error to the user
/// </summary>
void ReportError(string title, string message, Exception exception);
/// <summary>
/// Notifies the UI that the DataContext/Binding context has changed
/// </summary>
void SetSelectedItem(IRecord selectedItem);
/// <summary>
/// The actual UI object that is displayed on screen as the content of the page
/// </summary>
object PageElement { get; }
/// <summary>
/// Clears residual errors from the screen if they exist
/// </summary>
void ClearErrors();
/// <summary>
/// The record was saved. The selectedItem parameter will be the saved record from the server.
/// </summary>
void CurrentRecordSaved(IRecord selectedItem);
/// <summary>
/// This event occurs when the UI wants to notify the controller that a Save button has been clicked in the UI somewhere
/// </summary>
event EventHandler SaveClicked;
}
public interface IPanelUIController : ISavePageUIController
{
void CreateAndAddPanelFromContent(PagePanel pagePanel, double? panelHeight);
IEnumerable<IPagePanel> GetIPagePanelControls();
void SetHeader(IPanelHeader pageHeader);
void SetVisiblePanels(IList<bool> visiblePanels);
void HideAllPanels();
event EventHandler<RecordsSelectedRoutedEventArgs> PanelPageRecordsSelected;
}
Эти интерфейсы были успешно реализованы в Silverlight и Xamarin форм. Итак, похоже ли это на другой шаблон дизайна пользовательского интерфейса? Может ли кто-нибудь рекомендовать улучшения? Или, скажите мне, что мне нужно сделать, чтобы преобразовать это в более стандартный шаблон дизайна пользовательского интерфейса? Как насчет имен? Что я должен назвать здесь своими классами и интерфейсами?
Я могу видеть ваши очки здесь. Проблема в том, что IPage на самом деле не является представлением. Свойство PageElement - это объект пользовательского интерфейса, который платформа отображает на экране, но помимо этого интерфейс IPage действительно является контроллером. Исторически это называлось IPage, но я рассматривал возможность переименования его в IPageController. –
Было бы справедливо сказать, что PageElement не должен существовать на контроллере, но способ, которым работает наша система, заключается в том, что создается класс IPage, а затем добавлен элемент PageElement в Visual Tree. –
Я слышу вас - вот что я хотел бы сделать в качестве примера: предполагая, что IPage является контроллером, я бы просто назвал его IPageController. Он должен ограничиваться управлением элементами страницы и обновлением данных из службы. Эта служба должна быть отдельным объектом, который фактически работает. Таким образом, у вас будет элемент PageElement, содержащий элемент управления IPage в качестве члена. После этого IPageController будет иметь сервис (IPageService), так что методы SaveClickAsync действительно просто вызовут какой-то метод в вашем сервисе, чтобы справляться с сохранением и вещами такого характера. – prestonsmith