【问题标题】:GUI Design Pattern , MVP, Tab ControlGUI设计模式,MVP,选项卡控件
【发布时间】:2010-08-04 13:30:45
【问题描述】:

我有一个应用程序,其窗口类似于下面的窗口。

alt text http://a.imageshack.us/img137/7481/screenshotxh.jpg

这里的要求是当用户单击保存按钮时,所有内容都必须保存。 “保存”和“重置”按钮对所有选项卡都是“通用的”。 Hence, when the "Personal Information" tab is selected and "Save" is clicked the program should also save changes made in the "Friends" tab and changes made in the "Employment History" tab.

应用程序已经有以下代码,我想保留此代码:

-PersonalInformationView、PersonalInformationPresenter、PersonalInformationModel

-FriendsView、FriendsPresenter、FriendsModel

-EmploymentHistoryView、EmploymentHistoryPresenter、EmploymentHistoryModel

每个演示者都有一个保存方法。

问题是考虑到我想保留我已经拥有的代码,什么是一个好的设计模式。另外,我希望这个窗口也有模型、视图、演示者。或者也许我应该改写一下我的问题:在编程 MVP 时包含“子视图”、“子演示者”的最佳方式是什么

问候, 疯子

【问题讨论】:

    标签: design-patterns model view tabs mvp


    【解决方案1】:

    我个人建议制作一个抽象接口,ISaveable 或 osthing,并确保每个 Presenter 都实现这一点,而不是通过每个 Presenter 作为 ISaveable 的对象并保存每个。

    【讨论】:

    • ..但是从“主视图”的演示者我无法访问“子视图”的演示者(PersonalInformationView,FriendsView,EmploymentHistoryView)..我只能访问“子视图”本身...
    【解决方案2】:

    我会让您的新演示者将您的子演示者作为构造函数参数,例如:

    class DialogPresenter {
    
        private readonly IDialogView view;
        private readonly PersonalInformationPresenter personal;
        private readonly FriendsPresenter friends;
        private readonly EmploymentHistoryPresenter history;
    
        void DialogPresenter(IDialogView view, PersonalInformationPresenter personal, FriendsPresenter friends, EmploymentHistoryPresenter history) {
            this.view = view;
            this.personal = personal;
            this.friends = friends;
            this.history = history;
        }
    
        bool Display() {
            this.personal.Display();
            this.friends.Display();
            this.history.Display();
    
            return this.view.Display() == DialogResult.Ok;
        }
    
        void Save() {
            this.personal.Save();
            this.friends.Save();
            this.history.Save();
        }
    }
    

    当然,如果您的演示者之间有一个通用接口,则可以像这样简化(并使其更具可扩展性):

    class DialogPresenter {
    
        private readonly IDialogView view;
        private readonly IPresenters[] presenters;
    
        void DialogPresenter(IDialogView view, IPresenters[] presenters)
        {
            this.view = view;
            this.presenters = presenters;
        }
    
        bool Display() {
            foreach (var item in this.presenters)
                item.Display();
    
            return this.view.Display() == DialogResult.Ok;
        }
    
        void Save() {
            var validation = new List<string>();
    
            foreach (var item in this.presenters)
                validation.AddRange(item.Validate());
    
            if (validation.Count > 0) {
                    _view.ShowErrors(validation);
                    return;
            }
    
            foreach (var item in this.presenters)
                validation.AddRange(item.Save());
        }
    }
    

    编辑: 调用代码是这样的:

    void DisplayForm() {
    
        using (var frm = new frmDisplay) {
    
            //or just use DI to get the models etc
            var personal = new PersonalInformationPresenter(personalModel, frm.PersonalTab);    //some properties to expose your views
            var friends = new FriendsPresenter(friendslModel, frm.FriendsTab);
            var history = new EmploymentHistoryPresenter(employmentHistoryModel, frm.HistoryTab);
    
            var presenter = new DialogPresenter(frm, personal, friends, history);
            if (presenter.Display()) {    
                presenter.Save();
            }
        }
    }
    

    希望这是一些启发/帮助:)

    【讨论】:

    • 这确实提供了一些灵感。但是,我对此有以下问题。每个演示者的“保存”方法在保存之前进行数据验证,如果失败,将调用 view.DisplayValidationErrors() 并显示一个 msgbox(“缺少邮政编码”等)如果我选择要使用您建议的代码,用户将在第一个选项卡中获得一个用于验证错误的 msg.box,在第二个选项卡中获得一个用于验证错误的 msg.box ..但我希望将所有验证错误汇总在一个 msg.box 中.
    • 我已经更新了我的答案(第二个代码块)来展示我是如何处理这个问题的
    【解决方案3】:

    我的建议是使用 save 方法创建 ISaveableView。 您的每个视图都将实现该接口。 我猜你的标签实现了你描述的视图。当您单击保存按钮时,您可以将活动选项卡转换为 ISaveableView 并调用其保存方法

    【讨论】:

    • 嗨,这是一个很好的回应,但“保存”方法不是视图的一部分,而是演示者的一部分……但我想我可以制作一个“保存” " 视图中的方法,此方法将调用演示者的“保存”。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多