MVP = Model View Presenter
Allgemein C# .Net Pattern Sharepoint
Hatte das Vergnügen am Wochenende eine kleine Applikation zu schreiben mit der man die Photos aus einer Sharepoint-Bibliothek runterladen kann.
Sollte ungefähr so aussehen ->
Als Eingaben, werden Username, Password, URL, die Liste sowie ein Feldnamen für Subdirectories und ein Pfad erwartet.
Nix großes kann man in eine Winform in 2-3 Stunden reinprügeln.
Wollte aber mal ein Model View Presenter Pattern implementieren.
Kategorie Hatte das Vergnügen am Wochenende eine kleine Applikation zu schreiben mit der man die Photos aus einer Sharepoint-Bibliothek runterladen kann.
Sollte ungefähr so aussehen ->
Als Eingaben, werden Username, Password, URL, die Liste sowie ein Feldnamen für Subdirectories und ein Pfad erwartet.
Nix großes kann man in eine Winform in 2-3 Stunden reinprügeln.
Wollte aber mal ein Model View Presenter Pattern implementieren.
Vorteil des Pattern es ist Testbar und
man kann die View einfach austauschen.
Im Internetz gibt es ein paar Beispiele, ich habe meine Klassen so strukturiert ->
Interface für das Model ->
namespace ArchivePhotos.interfaces {
public delegate void ChangeMessageDelegate( string message );
public interface IListLibraryExportModel {
#region Properties
string List { get; set; }
List<string> Lists { get; set; }
string Password { get; set; }
string Username { get; set; }
string WebSiteUrl { get; set; }
#endregion
#region Events
event ChangeMessageDelegate ChangeMessageHandler;
#endregion
#region Methods
void ExportFiles(string exportDirectory, string directoryField);
void RetrieveLists();
#endregion
}
}
Hier habe ich einen ChangeMessageDelegate definiert, welcher im Model-Interface als Event definiert ist. Hierdurch kann ich dann beim iterieren über die Photos den Event feuern.
Da es dem Presenter freisteht an wen er ihn bindet, sollte natürlich im Interface der View evtl. eine Methode mit der Signatur des Delegates definiert werden ->
namespace ArchivePhotos.interfaces {
public delegate void RetrieveListsDelegate();
public delegate void ExportItemsDelegate();
public interface IListLibraryExportView {
#region Properties
string DirectoryField { get; set; }
string ExportDirectory { get; set; }
string List { get; set; }
List<string> Lists { get; set; }
string Password { get; set; }
string Username { get; set; }
string WebSiteUrl { get; set; }
#endregion
#region Events
event RetrieveListsDelegate RetrieveListsHandler;
event ExportItemsDelegate ExportItemsHandler;
#endregion
#region Methods
void SetMessage(string Message);
#endregion
}
}
Hier die Methode SetMessage!
Im Interface für die View werden auch zwei Events definiert RetrieveListsHandler und ExportItemsHandler. In manchen Beispielen im Netz wird hier der Default-Eventhandler benutzt. Aber das gefällt mit nicht, wegen den Parameter object o und EventArgs e, weil brauch ich eigentlich eh nicht, wenn der Button geklickt wird
Nun die Implementierung des Presenter ->
namespace ArchivePhotos.implementation {
public class ListLibraryExportPresenter {
IListLibraryExportView _view = null;
IListLibraryExportModel _model = null;
public ListLibraryExportPresenter( IListLibraryExportView view, IListLibraryExportModel model ) {
_view = view;
_model = model;
SetViewPortProperties();
BindEventHandler();
}
void BindEventHandler() {
_model.ChangeMessageHandler += _view.SetMessage;
_view.ExportItemsHandler += ExportItems;
_view.RetrieveListsHandler += RetrieveLists;
}
void SetViewPortProperties() {
_view.WebSiteUrl = _model.WebSiteUrl;
_view.Lists = _model.Lists;
_view.Password = _model.Password;
_view.Username = _model.Username;
_view.List = _model.List;
}
void SetModelProperties() {
_model.WebSiteUrl = _view.WebSiteUrl;
_model.Lists = _view.Lists;
_model.Username = _view.Username;
_model.Password = _view.Password;
_model.List = _view.List;
}
public void RetrieveLists() {
SetModelProperties();
_model.RetrieveLists();
SetViewPortProperties();
}
public void ExportItems() {
SetModelProperties();
_model.ExportFiles(_view.ExportDirectory,_view.DirectoryField);
}
}
}
Der Presenter bekommt im Konstruktor die Referenzen auf die View und das Model.
Mittels SetViewPortProperties werden die Daten vom Model and die View transferiert, SetModelProperties macht es vice versa. (Bin kein Freund von Databinding )
Der Konstruktor ist auch verantwortlich für das Binden der Eventhandler zwischen Model und View, jol und eigentlich war es das
Das Aufrufen der Form geht dann ungefähr so ->
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
IListLibraryExportView view = new cbLists();
IListLibraryExportModel model = new ListLibraryExportModel();
ListLibraryExportPresenter presenter = new ListLibraryExportPresenter(view,model);
Application.Run((Form)view);
Wenn ich die View durch ein Consolenprogramm austauschen möchte, kann ich dies wie folgt realisieren ->
class Program : IListLibraryExportView {
static void Main(string Array args) {
Program p = new Program();
ListLibraryExportModel model = new ListLibraryExportModel();
ListLibraryExportPresenter presenter = new ListLibraryExportPresenter(p,model);
p.DirectoryField = args(0);
p.Username = args(1);
p.Password = args(2);
p.List = args(3);
p.ExportDirectory = args(4);
p.WebSiteUrl = args(5);
presenter.ExportItems();
}
#region IListLibraryExportView Member
public string DirectoryField { get; set; }
public string ExportDirectory { set; get; }
public string List { get; set; }
public List<string> Lists { get; set; }
public string Password { get; set; }
public string Username { get; set; }
public string WebSiteUrl { get; set; }
public event RetrieveListsDelegate RetrieveListsHandler;
public event ExportItemsDelegate ExportItemsHandler;
public void SetMessage(string Message) {
System.Console.WriteLine(Message);
}
#endregion
}
Wupp und fertisch -> Result ->
Also angenehme Woche noch
Gruß JJR
Im Internetz gibt es ein paar Beispiele, ich habe meine Klassen so strukturiert ->
Interface für das Model ->
namespace ArchivePhotos.interfaces {
public delegate void ChangeMessageDelegate( string message );
public interface IListLibraryExportModel {
#region Properties
string List { get; set; }
List<string> Lists { get; set; }
string Password { get; set; }
string Username { get; set; }
string WebSiteUrl { get; set; }
#endregion
#region Events
event ChangeMessageDelegate ChangeMessageHandler;
#endregion
#region Methods
void ExportFiles(string exportDirectory, string directoryField);
void RetrieveLists();
#endregion
}
}
Hier habe ich einen ChangeMessageDelegate definiert, welcher im Model-Interface als Event definiert ist. Hierdurch kann ich dann beim iterieren über die Photos den Event feuern.
Da es dem Presenter freisteht an wen er ihn bindet, sollte natürlich im Interface der View evtl. eine Methode mit der Signatur des Delegates definiert werden ->
namespace ArchivePhotos.interfaces {
public delegate void RetrieveListsDelegate();
public delegate void ExportItemsDelegate();
public interface IListLibraryExportView {
#region Properties
string DirectoryField { get; set; }
string ExportDirectory { get; set; }
string List { get; set; }
List<string> Lists { get; set; }
string Password { get; set; }
string Username { get; set; }
string WebSiteUrl { get; set; }
#endregion
#region Events
event RetrieveListsDelegate RetrieveListsHandler;
event ExportItemsDelegate ExportItemsHandler;
#endregion
#region Methods
void SetMessage(string Message);
#endregion
}
}
Hier die Methode SetMessage!
Im Interface für die View werden auch zwei Events definiert RetrieveListsHandler und ExportItemsHandler. In manchen Beispielen im Netz wird hier der Default-Eventhandler benutzt. Aber das gefällt mit nicht, wegen den Parameter object o und EventArgs e, weil brauch ich eigentlich eh nicht, wenn der Button geklickt wird
Nun die Implementierung des Presenter ->
namespace ArchivePhotos.implementation {
public class ListLibraryExportPresenter {
IListLibraryExportView _view = null;
IListLibraryExportModel _model = null;
public ListLibraryExportPresenter( IListLibraryExportView view, IListLibraryExportModel model ) {
_view = view;
_model = model;
SetViewPortProperties();
BindEventHandler();
}
void BindEventHandler() {
_model.ChangeMessageHandler += _view.SetMessage;
_view.ExportItemsHandler += ExportItems;
_view.RetrieveListsHandler += RetrieveLists;
}
void SetViewPortProperties() {
_view.WebSiteUrl = _model.WebSiteUrl;
_view.Lists = _model.Lists;
_view.Password = _model.Password;
_view.Username = _model.Username;
_view.List = _model.List;
}
void SetModelProperties() {
_model.WebSiteUrl = _view.WebSiteUrl;
_model.Lists = _view.Lists;
_model.Username = _view.Username;
_model.Password = _view.Password;
_model.List = _view.List;
}
public void RetrieveLists() {
SetModelProperties();
_model.RetrieveLists();
SetViewPortProperties();
}
public void ExportItems() {
SetModelProperties();
_model.ExportFiles(_view.ExportDirectory,_view.DirectoryField);
}
}
}
Der Presenter bekommt im Konstruktor die Referenzen auf die View und das Model.
Mittels SetViewPortProperties werden die Daten vom Model and die View transferiert, SetModelProperties macht es vice versa. (Bin kein Freund von Databinding )
Der Konstruktor ist auch verantwortlich für das Binden der Eventhandler zwischen Model und View, jol und eigentlich war es das
Das Aufrufen der Form geht dann ungefähr so ->
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
IListLibraryExportView view = new cbLists();
IListLibraryExportModel model = new ListLibraryExportModel();
ListLibraryExportPresenter presenter = new ListLibraryExportPresenter(view,model);
Application.Run((Form)view);
Wenn ich die View durch ein Consolenprogramm austauschen möchte, kann ich dies wie folgt realisieren ->
class Program : IListLibraryExportView {
static void Main(string Array args) {
Program p = new Program();
ListLibraryExportModel model = new ListLibraryExportModel();
ListLibraryExportPresenter presenter = new ListLibraryExportPresenter(p,model);
p.DirectoryField = args(0);
p.Username = args(1);
p.Password = args(2);
p.List = args(3);
p.ExportDirectory = args(4);
p.WebSiteUrl = args(5);
presenter.ExportItems();
}
#region IListLibraryExportView Member
public string DirectoryField { get; set; }
public string ExportDirectory { set; get; }
public string List { get; set; }
public List<string> Lists { get; set; }
public string Password { get; set; }
public string Username { get; set; }
public string WebSiteUrl { get; set; }
public event RetrieveListsDelegate RetrieveListsHandler;
public event ExportItemsDelegate ExportItemsHandler;
public void SetMessage(string Message) {
System.Console.WriteLine(Message);
}
#endregion
}
Wupp und fertisch -> Result ->
Also angenehme Woche noch
Gruß JJR