2

Silverlightアプリケーションがあります。それは私たちのUIのタブ内に座っているいくつかのページがあります。過去にはSavePageとPanelPageと呼ばれてきました。保存ページには、レコードの詳細を編集したり、新しいレコードを作成したり、既存のレコードを画面上で削除したりするための基本的な機能があります。 PanelPageはSavePageから継承します。 PanelPageは、画面上での選択に基づいてパネルが表示/非表示になるという点で少し洗練されています。私はどのようなデザインパターンを完成させましたか?

コードはSilverlightアプリケーションで非常に混乱していました。しかし、最近、私はこのコードをXamarin Formsで動作させるための移植作業を行いました。私はこれを2回失敗しました。私の3回目の試みでは、Silverlight、iOS、Android、およびWindows UWPのすべての対象プラットフォームで動作するようになっています。今私はクラスデザインにかなり満足しています。それはより簡単かもしれませんが、これはしばらくの間、このトリックを行います。

このデザインのポイントは、UIロジックが物理UIコントロール自体から抽象化されている点です。私はSystem.Windowsを両方のプラットフォーム(SavePageとPanelPage)にまたがっている共有コードから削除しました。これらのページは、MVCまたはMVVCパターンの「コントローラ」によく似ています。しかし、私が作ったのは、まさにその2つのパターンのどちらかとは思えません。しかし、これらのクラスは、SaveAsync()のような抽象的なUI呼び出し用と、ReportErrorなどのプラットフォーム固有のUI呼び出し用の2つに分けなければなりませんでした。私は、私が使っているデザインパターンが分からないので、クラスの命名を得るのに苦労しています。ここ

は、クラス図である:ここ Class Diagram当該インターフェースのいくつかのコードです:

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フォームで正常に実施されています。だから、これは別のUIデザインパターンに似ていますか?誰も改善をお勧めできますか?または、これをより標準的なUIデザインパターンに変換するために必要なことを教えてください。名前はどうですか?クラスとインターフェイスの名前はここでどうすればよいですか?

答えて

2

正直言って、どちらか一方(MVC、MVVM、MVP)に執着することはあまりありません。彼らはほとんど同じであり、そのポイントは "大きな分割"を維持することです。それは今、あなたがMVPに最も近いように見える私見(モデルビュープレゼンター)

問題はあなたがそこに混ざりロジックの多くを持っているということである、と述べた:IPageは本当にただViewする必要がありますが、あなたはそれをやっていコントローラーが典型的にするもの。子どもと同じです:ISavePageには、Controllerで見ると通常期待しているSetAutomationというオブジェクトのメソッドがあります(少なくとも私がその関数を正しく推測しているならば)。

Adam Freemanは、ASP.NET MVC 5でこれをどのように壊すのかについて話してくれました。http://enos.itcollege.ee/~ijogi/Nooks/Pro%20ASP.NET%20MVC%205/Pro%20ASP.NET%20MVC%205.9781430265290.pdf 51ページを参照して、各項目を概念的に理解する必要があります。

あなたのIPageが実際にコントローラであることがわかったので、この方法でやり直してみます。

public class PageElement 
{ 
    IPageController _controller; 

    // these are your models - your controller will simply allow them to be shown with your other methods 
    private PageData _data; 
    private PageData _otherData; 

    public PageElement(IPageController ctrl) 
    { 
     _controller = ctrl; 
    } 
} 

public class PageController : IPageController 
{ 
    IPageService _service; 

    public PageController(IPageService service) 
    { 
      _service = service; 
    } 

    // this is what your button calls when clicked 
    public void SaveAsync(object sender, SomeEventArgs args) 
    { 
      // the service does the actual work 
      _service.SaveAsync() 
    } 
} 

public class PageService : IPageService 
{ 
    public void SaveAsync(){ // what it does} 

} 
+0

私はここにあなたのポイントを見ることができます。問題はIPageが本当にビューではないということです。 PageElementプロパティはプラットフォームが画面に表示するUIオブジェクトですが、それ以外のIPageインターフェイスは実際はコントローラです。歴史的にはIPageと呼ばれていましたが、私はIPageControllerに名前を変更することを検討してきました。 –

+0

PageElementがコントローラに存在してはいけないと言うのは間違いありませんが、私たちのシステムの仕組みは、IPageクラスがインスタンス化され、次にPageElementがVisual Treeに追加されるということです。 –

+0

私はあなたの話を聞いています - ここでは私が一例として行うことです:IPageがコントローラであると仮定すると、IPageControllerと呼ぶだけです。それは、ページ要素を管理し、サービスからデータを更新することに限定されるべきである。そのサービスは、実際に機能する個別のオブジェクトでなければなりません。つまり、IPageControllerをメンバーとして含むPageElementがあります。 IPageControllerはサービス(IPageService)を所有するので、メソッドSaveClickAsyncは実際にサービス内のメソッドを呼び出すだけで、その性質や性質を保存することができます。 – prestonsmith

0

MVCのように見える、または(前MVC)は、前のコントローラビューパターン

関連する問題