MVC,MVP,MVVM(补充)
when evaluating a pattern, it is really important to at details such as:
- How are view and controller conntected?
- How an user action from the view is sent to controller?
- Who is responsible for updating the view?
一个mvc的例子:http://expression.microsoft.com/en-us/cc964002.aspx
用view创建 controller,view的动作捆绑到controller中,model通知view数据的变化。
public partial class Page : UserControl
{
private Controllers.Controller _controller;
public Page()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(Page_Loaded);
}
void Page_Loaded(object sender, RoutedEventArgs e)
{
_controller = new Controllers.Controller(this);
_controller.Initialize();
}
}
------------------------------------------------------------------------------------
public Controller(Page pageView)
{
_pageView = pageView;
_shellView = new Game.Views.Shell(new Models.Shell()); (model)
_pageView.LayoutRoot.Children.Add(_shellView);
}
private Storyboard _sbTick = new Storyboard();
public void Initialize()
{
//setup my game timer
_sbTick.Duration = TimeSpan.FromMilliseconds(10);
_sbTick.Completed += new EventHandler(_sbTick_Completed);
//place the start dialog into the shell
_startView = new Views.Start();
//attach to the start event of the view
_startView.Begin += new
Game.Views.Start.BeginHandler(_startView_Begin);
//add the view to the shell
_shellView.LayoutRoot.Children.Add(_startView);
}
-------------------------------------------------------------
shell,用来插入view
<UserControl x:Class="Game.Views.Shell"
xmlns="http://schemas.microsoft.com/client/2007"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="450" Height="450">
<Grid x:Name="LayoutRoot" Background="WhiteSmoke" Cursor="None">
<Grid Width="450" Height="400" x:Name="Container" VerticalAlignment="Top"
Background="Transparent"/>
<Rectangle Margin="0,0,0,50" Height="30" Width="50"
Fill="Black" VerticalAlignment="Bottom"
HorizontalAlignment="Center"></Rectangle>
<Grid Width="450" Height="50" x:Name="Statusbar" Background="Black"
HorizontalAlignment="Center" VerticalAlignment="Bottom">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="60" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Margin="0,0,0,0" FontSize="20"
Text="Score:" TextAlignment="Right" Foreground="White"
HorizontalAlignment="Right" VerticalAlignment="Center"/>
<TextBlock Grid.Column="1" Margin="0,0,15,0" x:Name="tbScore"
FontSize="20" Text="0" TextAlignment="Right" Foreground="White"
HorizontalAlignment="Right" VerticalAlignment="Center"/>
</Grid>
</Grid>
</UserControl>
public partial class Shell : UserControl
{
private Models.Shell _model;
public Models.Shell Model
{
get { return _model; }
}
public Shell(Models.Shell model)
{
InitializeComponent();
_model = model;
_model.UpdateScore += new Game.Models.Shell.UpdateScoreHandler(_model_UpdateScore); //用model事件来通知view,比较拙劣
}
void _model_UpdateScore(object sender, int points)
{
tbScore.Text = points.ToString(); // 因为没有view model,这些操作在view中来做,绑定无用武之地
}
public class Shell
{
public delegate void UpdateScoreHandler(object sender, int points);
public event UpdateScoreHandler UpdateScore;
private int _score = 20;
public int Score
{
get { return _score; }
set {
_score = value;
OnUpdateScore();
}
}
protected void OnUpdateScore()
{
if (UpdateScore != null)
{
UpdateScore(this, Score);
}
}
---------------------------------------------------------\ Controller
Public void StartGame()
{
....
_shellView.MouseEnter += new MouseEventHandler(_shellView_MouseEnter);
_shellView.MouseLeave += new MouseEventHandler(_shellView_MouseLeave);
_shellView.MouseMove += new MouseEventHandler(_shellView_MouseMove);
_shellView.MouseLeftButtonDown +=
new MouseButtonEventHandler(_shellView_MouseLeftButtonDown);
//add the crosshair
Crosshair cross = new Crosshair(new Vector(0.0, 0.0));
_crosshair = new Game.Views.Crosshair(cross);
_shellView.Container.Children.Add(_crosshair);
....
}
void _shellView_MouseMove(object sender, MouseEventArgs e)
{
Point m = e.GetPosition(_shellView.Container);
_crosshair.Model.Move(_shellView.Container, m);
_player.Model.ChangeAngle(m);
}
void _shellView_MouseLeave(object sender, MouseEventArgs e)
{
_shellView.CaptureMouse();
}
void _shellView_MouseEnter(object sender, MouseEventArgs e)
{
_shellView.CaptureMouse();
}
void _shellView_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
. . . .
}
一个mvp的例子:http://timross.wordpress.com/2008/03/16/implementing-the-mvp-pattern-in-silverlight/
MVVM (Model-View-ViewModel)前面的文章介绍过。微软的prism V2用的是这个(presenterModel,presenter)
Composite Application Guidance for WPF and Silverlight
http://msdn.microsoft.com/en-us/practices/default.aspx
Server Application
The main database, domain model and business logic reside on the server. The data and business logic is accessed by the Silverlight application through calls to Web Services. The server application can be architected independently and is not specific to the MVP Pattern.
Silverlight Client
The Silverlight client application contains only presentation logic and no business logic. Any operations that require business logic should be passed back to the server to be processed and results returned in the form of a Data Transfer Object (DTO).
Service Reference
The Silverlight application talks to the server via web services. Visual Studio creates a service reference that contains methods for making asynchronous calls to a web service. We can create a partial class from the generated service soap client that implements a custom interface containing methods used by the presenter. We can then call service methods through this interface rather than directly referencing the service class. Using an interface also allows us to stub-out the service when unit testing the presenter.
Proxy Model
When the Silverlight application references a web service, a proxy data class is generated. This class acts as a Data Transfer Object (DTO) that represents a data structure for transferring data between the client and server applications. The DTO provides the model used by the view and presenter.
View
The view is the visual representation of the application.
The view is composed of XAML files and their corresponding code-behind files. This structure is very similar to that of an ASP.NET page.
The XAML files describe the layout and behavior of the Silverlight interface. Controls in the view are wrapped by properties in the code-behind file. Any events fired from controls are handled in the code-behind and passed up to the presenter for further processing. The presenter can also pass information back to the view through properties and methods in the code-behind.
Presenter
The presenter sits between the view and the service reference. If the view requests data, the presenter will call a service reference and present the results to the view. If an action requires logic, the presenter will handle the event and process the information to send back to the view.