【发布时间】:2018-09-10 17:15:29
【问题描述】:
我有一个 WinForms 应用程序设置来使用 Model View Presenter。为了避免视图了解模型,我正在考虑让演示者使用视图实例来访问视图文本框并将它们数据绑定到演示者也拥有的模型实例。采用这种方法有什么问题?
我考虑过的另一个选项是让视图具有模型的实例。模型属性将具有 INotifyPropertyChanged 设置。在这种情况下,我可以让视图将数据绑定设置为它拥有的文本框和它也拥有的模型实例。这样做有什么问题?
我考虑的另一个选项是将模型属性复制到演示器中并使用 INotifyPropertyChanged 进行设置。然后,视图具有演示者的实例,我可以让视图数据将其文本框绑定到演示者中的匹配属性。使用此设置,当演示者进行数据访问调用时,它会为自身的属性设置值,这将自动更新数据绑定到演示者属性的视图文本框。
如果我不使用数据绑定,我只会在视图中添加 getter 和 setter,以便演示者访问视图文本框的值。演示者将使用视图获取器和设置器来执行数据访问调用。在从数据访问调用接收数据后,演示者还将使用 setter 设置视图文本框的值。
我正在考虑的这些选项基于我看过的文章,但也许还有另一种方法可以在我没有见过的 WinForms MVP 实现中管理数据。请就推荐的方法提供反馈,用于管理从视图到演示者或模型的数据来回管理,或者可能需要在此处添加另一层,例如某种服务? 提前致谢。
================================== 2018 年 4 月 10 日更新
我能够设置我的应用程序,使 View 和 Model 不引用 Presenter,同时允许 Presenter 引用 View 和 Model。这成为可能,因为我发现了如何从 Presenter 中将视图绑定到其控件所需的数据。这样就不需要让 Presenter 直接访问属于 View 的可视控件。
DepartmentPresenter 字段:
public class DepartmentPresenter : IDepartmentPresenter
{
private IDepartmentView departmentView;
private IDepartmentModel departmentModel;
private IDepartmentRepository departmentRepository;
....
}
这是 Presenter 的实例化:
void OnDisplayDepartmenSelectedRaised(object sender, DisplayDepartmentSelectedEventArgs e)
{
//Get current selected data row from Presenters BindingSource which used by the View to bind
//to its DataGridView. The view only knew it wasw a BindingSource and never had to know it
//was a collectino of DepartmentModel Data Transfer Objects (DTOs)
selectedDepartmentModel = (DepartmentModel)departmentModelBindingSource.Current;
DepartmentPresenter aDepartmentPresenter = new DepartmentPresenter(departmentView,
departmentRepository,
selectedDepartmentModel.DepartmentId);
}
Presenter 构造函数:
public DepartmentPresenter(IDepartmentView departmentView,
IDepartmentRepository departmentRepository,
int selectedDepartmentId)
{
this.departmentRepository = departmentRepository;
departmentModel = departmentRepository.GetById(selectedDepartmentId);
this.departmentView = departmentView;
//Subscribe to View's save request from save button so Presenter can perform work to be done on a save
this.departmentView.SaveDepartmentRaised += new EventHandler(OnSaveDepartmentRaised);
//Create bindings for data the View will use on its textBoxes
Binding departmentNameBinding = new Binding("Text", DepartmentModel, "DepartmentName", true, DataSourceUpdateMode.OnPropertyChanged);
Binding cityLocationBinding = new Binding("Text", departmentModel, "CityLocation", true, DataSourceUpdateMode.OnPropertyChanged);
Binding stateLocationBinding = new Binding("Text", departmentModel, "StateLocation", true, DataSourceUpdateMode.OnPropertyChanged);
//Store bindings into a dictionary for the View to access for its textBoxes
Dictionary<string, Binding> bindingDictionary = new Dictionary<string, Binding>();
bindingDictionary.Add("DepartmentName", departmentNameBinding);
bindingDictionary.Add("CityLocation", cityLocationBinding);
bindingDictionary.Add("StateLocation", stateLocationBinding);
//Use passed in reference to View to tell view to bind its textBoxes using the passed in Dictionary of bindings
this.departmentView.BindDisplayData(bindingDictionary);
this.departmentView.ShowView();
}
下面是 View 如何绑定到它的 textBox 控件以响应 Presenter 告诉它这样做:
public void BindDisplayData(Dictionary<string, Binding> bindingDictinary)
{
textBoxName.DataBindings.Add(bindingDictinary["DepartmentName"]);
textBoxCity.DataBindings.Add(bindingDictinary["CityLocation"]);
textBoxState.DataBindings.Add(bindingDictinary["StateLocation"]);
}
View 的接口定义如下:
public interface IDepartmentView
{
event EventHandler SaveDepartmentRaised;
void ShowView();
void BindDisplayData(Dictionary<string, Binding> bindingDictinary);
}
希望这将有助于尝试从模型视图演示器项目中的演示器绑定到视图的人,同时避免使视图具有演示器的实例。
【问题讨论】:
-
为什么不使用 MVVM?恕我直言,这是比 MVP 更好的模式。
标签: c# winforms data-binding mvp