Nous avons une application Silverlight. Il a quelques pages qui se trouvent à l'intérieur des onglets de notre interface utilisateur. Dans le passé, nous les avons appelés SavePage et PanelPage. La page d'enregistrement ne dispose que des fonctionnalités de base pour éditer les détails d'un enregistrement, créer de nouveaux enregistrements et supprimer l'enregistrement existant à l'écran. PanelPage hérite de SavePage. PanelPage est un peu plus sophistiqué dans la mesure où les panneaux deviennent visibles/invisibles en fonction des sélections que vous faites à l'écran.Quel motif de conception ai-je trouvé?
Le code était un désordre énorme dans l'application Silverlight. Mais, récemment, j'ai pris l'étape du portage de ce code pour travailler dans Xamarin Forms. J'ai fait deux tentatives ratées pour ce faire, et lors de ma troisième tentative, j'ai obtenu le code pour travailler sur toutes les plates-formes ciblées: Silverlight, iOS, Android et Windows UWP. Je suis assez content de la conception de la classe pour le moment. Cela pourrait être plus simple, mais cela fera l'affaire pendant un moment.
Le but de cette conception est que la logique d'interface utilisateur soit séparée des contrôles d'interface utilisateur physiques eux-mêmes. J'ai supprimé les utilisations System.Windows du code partagé qui se trouve sur les deux plates-formes (SavePage et PanelPage). Ces pages sont plus comme des «contrôleurs» dans les modèles MVC ou MVVC. Mais, je ne pense pas que ce que j'ai créé est exactement l'un ou l'autre de ces deux modèles. Cependant, j'ai dû diviser ces classes en deux parties: une pour les appels abstraits de l'interface utilisateur comme SaveAsync(), et une pour les appels d'interface utilisateur spécifiques à la plate-forme comme ReportError. Je me bats pour obtenir le nom des classes juste puisque je ne sais même pas quel modèle de conception j'utilise.
Voici un diagramme de classes: Voici le code pour certaines des interfaces concernées:
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;
}
Ces interfaces ont été mises en œuvre avec succès dans les formulaires Silverlight et Xamarin. Donc, est-ce similaire à un autre modèle de conception d'interface utilisateur? Quelqu'un peut-il recommander des améliorations? Ou, dites-moi ce que je devrais faire pour le convertir en un modèle de conception d'interface utilisateur plus standard? Que diriez-vous de nommer? Que dois-je nommer mes classes et interfaces ici?
Je peux voir vos points ici. Le problème est que IPage n'est pas vraiment une vue. La propriété PageElement est l'objet UI que la plate-forme va afficher à l'écran, mais à part ça, l'interface IPage est vraiment le contrôleur. Historiquement, il s'appelait IPage, mais j'ai envisagé de le renommer IPageController. –
Il serait juste de dire que PageElement ne devrait pas exister sur le contrôleur, mais la façon dont notre système fonctionne est qu'une classe IPage est instanciée, puis l'élément PageElement est ajouté à l'arborescence Visual. –
Je vous entends - voici ce que je ferais comme exemple: en supposant que IPage est le contrôleur, je l'appellerais simplement IPageController. Il devrait être limité à la gestion des éléments de page et à la mise à jour des données d'un service. Ce service devrait être un objet distinct qui fonctionne réellement. Donc vous auriez un PageElement qui contient un IPageController en tant que membre. Le IPageController devrait alors avoir son propre service (IPageService) pour que les méthodes SaveClickAsync appellent simplement une méthode dans votre service pour gérer la sauvegarde et les choses de cette nature. – prestonsmith