Jag har ända sedan ASP.NET MVC annonserades intresserat mig för det mönstret och försökt att läsa på så mycket det bara gått. Jag antar att jag borde ha sett nyttan och skönheten långt tidigare, men det har hela tiden funnits andra tekniker att också intressera sig för.
Det som jag också noterade under en workshop på Mobil Business konferensen var att hela utvecklingsmodellen för applikationer på iPhone var baserade på samma mönster. Då tänkte jag så klart att vi vill inte vara sämre på Windows Phone så först började jag skissa själv på en sådan implementation, men kom samtidigt på att det finns flera implementationer på Windows-sidan, sedan tidigare som borde vara lätta att migrera. Därför började jag istället söka lite och stötte omedelbart på ett ramverk som heter Mobile MVC och som naturligtvis finns publicerat på CodePlex. Det har jag därför börjat att läsa på lite om och lyckats att skapa lite roliga exempel på användning.
Här är en introduktion till Mobile MVC:
Jag börjar med att skapa ett nytt projekt för Windows Mobile med 6.5 som SDK och alltså .NET Compact Framework 3.5 som “runtime”. Efter det så lägger jag till referenser till System.Mobile.Mvc.dll och Microsoft.Practices.Mobile.ContainerModel.dll, båda dessa kan fås genom att ladda hem Mobile MVC från CodePlex. Jag skapar också en projektstruktur med lite mappar för att få ordning på de filer vi snart ska skriva och resultatet kan ses här till höger!
Det jag sedan också vill lägga till direkt är möjligheten för lite mer löst kopplade klasser och därför använda Dependency Injection, därför lägger jag till två stycken klasser som kan hittas i exempelkoden till Mobile MVC, men här följer dessa filers kod, den första filen heter helt enkelt ControllerProvider.cs och används för att instansiera mina controllers framöver.
public class ControllerProvider : IControllerProvider
{
private Container container;
public ControllerProvider(Container container)
{
this.container = container;
}
#region IControllerProvider Members
public Controller GetController(string name)
{
throw new NotImplementedException();
}
public Controller GetController(Type type)
{
throw new NotImplementedException();
}
public Controller GetController<T>()
{
return this.container.Resolve<T>() as Controller;
}
public Controller GetController<T>(IView view)
{
Controller controller = this.container.Resolve<Controller>();
controller.View = view;
return controller;
}
public void RegisterController(Controller controller)
{
throw new NotImplementedException();
}
#endregion
}
Den andra filen heter ApplicationManager.cs och används för att konfigurera upp den ControllerProvider som tidigare skrevs. Här är koden för den filen:
public class ApplicationManager
{
private static Container container;
static ApplicationManager()
{
Initialize();
}
private static void Initialize()
{
container = new Container();
// TODO add registration here
Navigator.SetControllerProvider(new ControllerProvider(container));
}
public static void Start()
{
// TODO add initialization here
}
}
Som synes så finns det lite kvar att lägga till innan applikationen kommer att fungera, men det kommer vi till snart.
Nu börjar vi att lägga till en controller, förslagsvis i mappen Controllers. Den får heta MainController och har för avsikt att visa en vy och sedan låta användaren helt enkelt terminera applikationen vid ett sådan menyval i vyn. Vi kommer inte ens att jobba med data utan bara introducera koncepten i mvc-mönstret för mobilen. Hela controllern ser ut så här:
public class MainController : Controller
{
public MainController(IView view): base(view) { }
public Container Container { get; set; }
private void OnExit(object sender, EventArgs e)
{
Application.Exit();
}
}
Klassen ärver av Controller-basklassen och konstruktorn tar som synes emot en vy som kopplas till controllern. Sedan finns det en lokal variabel för containern som används för att hitta andra klasser och tjänster med dependency injection-mönstret. Den sista metoden OnExit kommer att användas för att vyn ska kunna kommunicera med controllern på löst kopplade sätt. Det är den metoden som avslutar applikationen.
Låt mig sedan lägga till vår enda vy, smakfullt kallas den MainView och är helt enkelt ett vanligt Formulär för Windows Mobile.
Jag gör två förändringar på formuläret i design-läge, det ena är att lägga till en label med lite text som gör applikationen till vad den är och det andra är att lägga till ett menyalternativ för att kunna avsluta applikationen, detta meny-alternativ får heta menuExit och så här ser mitt formulär ut. Jag genererar också en event-handler för menuExit.Click händelsen.
Sedan byter jag till kodläge och uppdaterar koden till att se ut som följer:
public partial class MainView : ViewForm
{
[PublishEvent("OnExit")]
public event EventHandler OnExitEvent;
public MainView()
{
InitializeComponent();
}
private void menuExit_Click(object sender, EventArgs e)
{
if (OnExitEvent != null)
{
this.OnExitEvent(this, EventArgs.Empty);
}
}
}
Även här ärver jag från en ny klass och i det här fallet så heter basklassen ViewForm, observera gärna att det ändå inte påverkar design-läget utan jag kan fortsätta att jobba med den visuella designern för kontroller och element på vyn.
Attributet [PublishEvent(“OnExit”)] låter controllern få reda på att en händelse har uppstått i vyn när den händelsen triggas och det som jag sedan gör i menuExit_Click är först att kontrollera om det finns någon “prenumerant” på händelsen och i sådant fall se till att anropa den prenumeranten.
Nu behöver jag bara registrera alla komponenter i containern och se till att starta applikationen. Registreringen sker i ApplicationManager enligt följande kod:
private static void Initialize()
{
container = new Container();
container.Register<MainView>(c => new MainView());
container.Register<MainController>(
c => new MainController(
c.Resolve<MainView>())).InitializedBy(
(c, v) => v.Container = c);
Navigator.SetControllerProvider(new ControllerProvider(container));
}
I samma fil lägger jag också till initaliseringskoden för att starta applikationen:
public static void Start()
{
var mainController = container.Resolve<MainController>();
mainController.Initialize();
Application.Run(mainController.View as Form);
}
Det sista som behövs är att se till att starta hela härligheten i Program-klassens Main-metod enligt följande lilla rad:
ApplicationManager.Start();
Sedan kör jag applikationen och hör och häpna, ett formulär öppnar sig och när jag väljer meny-alternativet Exit så avslutas den.
Det här var som sagt bara en introduktion till MVC-mönstret på Windows Mobile, nu börjar det roliga, att hämta data, koppla data från modeller till kontroller i vyer, kommunicera mellan kontroller till vyer och andra kontroller, navigera fram och tillbaka och massa annat gott som jag får försöka att skriva om framöver på svenska. Men kan du inte hålla dig utan redan nu vill lära dig mer och läsa om vad Alex har skapat med sitt ramverk så finns det ytterligare artiklar på engelska på hans blogg:
- Mobile MVC Framework (part 1)
- Mobile MVC Framework (part 2)
- Mobile MVC Framework (part 3) – communicating with events
- Mobile MVC Framework (part 4) – passing data between controllers
- Mobile MVC Framework – Update with Dependency Injection