Đây là lời khiêm tốn của tôi về MVP và các vấn đề cụ thể của bạn.
Đầu tiên , bất kỳ thứ gì mà người dùng có thể tương tác hoặc chỉ được hiển thị đều là một chế độ xem . Các luật, hành vi và đặc điểm của dạng xem như vậy được mô tả bằng một giao diện . Giao diện đó có thể được triển khai bằng cách sử dụng giao diện người dùng WinForms, giao diện người dùng bảng điều khiển, giao diện người dùng web hoặc thậm chí không có giao diện người dùng nào (thường là khi thử nghiệm người thuyết trình) - việc triển khai cụ thể không quan trọng miễn là nó tuân theo luật của giao diện xem của nó .
Thứ hai , một chế độ xem luôn được kiểm soát bởi người trình bày . Luật, hành vi và đặc điểm của một người thuyết trình như vậy cũng được mô tả bằng một giao diện . Giao diện đó không quan tâm đến việc triển khai chế độ xem cụ thể miễn là nó tuân theo luật của giao diện chế độ xem của nó.
Thứ ba , vì người thuyết trình kiểm soát chế độ xem của nó, nên để giảm thiểu sự phụ thuộc, thực sự không có lợi gì khi chế độ xem biết bất cứ điều gì về người thuyết trình của nó. Có một hợp đồng đã đồng ý giữa người trình bày và chế độ xem và điều đó được nêu trong giao diện chế độ xem.
Ý nghĩa của Thứ ba là:
- Người trình bày không có bất kỳ phương thức nào mà chế độ xem có thể gọi, nhưng chế độ xem có các sự kiện mà người trình bày có thể đăng ký.
- Người thuyết trình biết quan điểm của nó. Tôi thích thực hiện điều này với phương pháp tiêm chất xây dựng trên người trình bày bê tông.
- Chế độ xem không có ý tưởng gì về người trình bày đang kiểm soát nó; nó sẽ không bao giờ được cung cấp cho bất kỳ người thuyết trình nào.
Đối với vấn đề của bạn, phần trên có thể trông giống như thế này trong mã được đơn giản hóa một chút:
interface IConfigurationView
{
event EventHandler SelectConfigurationFile;
void SetConfigurationFile(string fullPath);
void Show();
}
class ConfigurationView : IConfigurationView
{
Form form;
Button selectConfigurationFileButton;
Label fullPathLabel;
public event EventHandler SelectConfigurationFile;
public ConfigurationView()
{
// UI initialization.
this.selectConfigurationFileButton.Click += delegate
{
var Handler = this.SelectConfigurationFile;
if (Handler != null)
{
Handler(this, EventArgs.Empty);
}
};
}
public void SetConfigurationFile(string fullPath)
{
this.fullPathLabel.Text = fullPath;
}
public void Show()
{
this.form.ShowDialog();
}
}
interface IConfigurationPresenter
{
void ShowView();
}
class ConfigurationPresenter : IConfigurationPresenter
{
Configuration configuration = new Configuration();
IConfigurationView view;
public ConfigurationPresenter(IConfigurationView view)
{
this.view = view;
this.view.SelectConfigurationFile += delegate
{
// The ISelectFilePresenter and ISelectFileView behaviors
// are implicit here, but in a WinForms case, a call to
// OpenFileDialog wouldn't be too far fetched...
var selectFilePresenter = Gimme.The<ISelectFilePresenter>();
selectFilePresenter.ShowView();
this.configuration.FullPath = selectFilePresenter.FullPath;
this.view.SetConfigurationFile(this.configuration.FullPath);
};
}
public void ShowView()
{
this.view.SetConfigurationFile(this.configuration.FullPath);
this.view.Show();
}
}
Ngoài những điều trên, tôi thường có một IView
giao diện cơ sở nơi tôi lưu trữ Show()
và bất kỳ chế độ xem chủ sở hữu hoặc chế độ xem nào mà các chế độ xem của tôi thường được hưởng lợi.
Đối với câu hỏi của bạn:
1. Khi winform tải, nó phải có được dạng cây. Tôi có đúng khi nghĩ rằng do đó chế độ xem nên gọi một phương thức như: presenter.gettree (), điều này đến lượt nó sẽ ủy quyền cho mô hình, sẽ lấy dữ liệu cho chế độ xem dạng cây, tạo nó và định cấu hình nó, trả về người thuyết trình, đến lượt nó sẽ chuyển đến chế độ xem mà sau đó sẽ chỉ định nó cho một bảng điều khiển?
Tôi sẽ gọi IConfigurationView.SetTreeData(...)
từ IConfigurationPresenter.ShowView()
, ngay trước cuộc gọi tớiIConfigurationView.Show()
2. Điều này có giống nhau đối với bất kỳ điều khiển dữ liệu nào trên Winform không, vì tôi cũng có một datagridview?
Vâng, tôi sẽ gọi IConfigurationView.SetTableData(...)
cho điều đó. Tùy thuộc vào chế độ xem để định dạng dữ liệu được cung cấp cho nó. Người trình bày chỉ cần tuân theo hợp đồng của chế độ xem rằng nó muốn dữ liệu dạng bảng.
3. Ứng dụng của tôi, có một số lớp mô hình với cùng một lắp ráp. Nó cũng hỗ trợ kiến trúc plugin với các plugin cần được tải khi khởi động. Chế độ xem có chỉ đơn giản gọi một phương thức trình bày, mà sau đó sẽ gọi một phương thức tải các plugin và hiển thị thông tin trong chế độ xem? Sau đó, cấp nào sẽ kiểm soát các tham chiếu plugin. Chế độ xem sẽ giữ các tham chiếu đến họ hoặc người trình bày?
Nếu các plugin có liên quan đến chế độ xem, thì các chế độ xem phải biết về chúng chứ không phải người trình bày. Nếu tất cả đều là về dữ liệu và mô hình, thì chế độ xem sẽ không liên quan gì đến chúng.
4. Tôi có đúng khi nghĩ rằng dạng xem nên xử lý mọi thứ về bản trình bày, từ màu của nút dạng cây, đến kích thước lưới dữ liệu, v.v.?
Đúng. Hãy nghĩ về nó như người trình bày cung cấp XML mô tả dữ liệu và dạng xem lấy dữ liệu và áp dụng biểu định kiểu CSS cho nó. Nói một cách cụ thể, người thuyết trình có thể gọi IRoadMapView.SetRoadCondition(RoadCondition.Slippery)
và chế độ xem sau đó hiển thị đường bằng màu đỏ.
Còn về dữ liệu cho các nút được nhấp?
5. Nếu khi tôi nhấp vào các sơ đồ hình cây, tôi có nên chuyển qua nút cụ thể cho người trình bày và sau đó từ đó người trình bày sẽ tìm ra dữ liệu mà nó cần và sau đó hỏi mô hình cho dữ liệu đó, trước khi trình bày trở lại khung nhìn?
Nếu có thể, tôi sẽ chuyển tất cả dữ liệu cần thiết để trình bày cái cây trong một khung cảnh trong một lần chụp. Nhưng nếu một số dữ liệu quá lớn để được chuyển ngay từ đầu hoặc nếu dữ liệu đó tự động và cần "ảnh chụp nhanh mới nhất" từ mô hình (thông qua trình trình bày), thì tôi sẽ thêm một cái gì đó tương tự event LoadNodeDetailsEventHandler LoadNodeDetails
vào giao diện xem, để Người trình bày có thể đăng ký nó, tìm nạp chi tiết của nút trong LoadNodeDetailsEventArgs.Node
(có thể thông qua ID của nó ở một số loại) từ mô hình, để chế độ xem có thể cập nhật chi tiết nút được hiển thị của nó khi người ủy quyền trình xử lý sự kiện trả về. Lưu ý rằng có thể cần các mẫu không đồng bộ của điều này nếu việc tìm nạp dữ liệu có thể quá chậm đối với trải nghiệm người dùng tốt.