Inquiridor
ASP.NET WebForms MVVP

Discussão Geral
-
Estava fazendo uns testes em relação ao assunto acima... e descobri uma forma de viabilizar a metodologia MVVP em WebForms...
Não fiz muitos testes ainda.. é so uma ideia no momento, mas resolvi compartilhar aqui caso alguem queira dar continuidade.... o fonte completo estou colocando aqui https://skydrive.live.com/redir?resid=B3A201D150ACCEA!986
Segue um exemplo de como esta funcionando a pagina...
View:
<%@ Page Language="C#" Inherits="Nomad.ASPMVVM.PageView" ViewModel="ASP.MVVM.ViewModel.TesteViewModel" %> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title></title> </head> <body> <form id="form1" runat="server"> <div> <asp:TextBox runat="server" Binding='[{ "Property" : "Text", "Path" : "Valor" }]'/> <asp:Label runat="server" Binding='[{ "Property" : "Text", "Path" : "Dobro" }]'/> <asp:Button Text="Dobrar" runat="server" CommandName="Dobrar" OnCommand="ActionCommand"/> </div> </form> </body> </html>
View Model:
using Nomad.ASPMVVM; using System; namespace ASP.MVVM.ViewModel { [Serializable] public class TesteViewModel: INotifyPropertyChanged { private int _valor; private int _dobro; public int Valor { get { return _valor; } set { if (Object.Equals(_valor, this) != true) { _valor = value; OnPropertyChanged("Valor"); } } } public int Dobro { get { return _dobro; } set { if (Object.Equals(_dobro, this) != true) { _dobro = value; OnPropertyChanged("Dobro"); } } } public event EventHandler<PropertyChangedEventArgs> PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { var handler = this.PropertyChanged; if (handler != null) { handler.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } public void Dobrar() { this.Dobro = this.Valor * 2; } } }
Microsoft Community Contributor
Todas as Respostas
-
Estou colocando tambem a classe PageView para dar uma ilustrada melhor com funciona a "engine"
using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Web.UI; using System.Web.UI.WebControls; namespace Nomad.ASPMVVM { [Serializable] public class PageView : Page { private readonly IDictionary<Control, BindingProperty[]> bindingProperties = new Dictionary<Control, BindingProperty[]>(); private object ViewModelState { get { return Context.Items["ViewModelState"]; } set { Context.Items.Remove("ViewModelState"); Context.Items.Add("ViewModelState", value); } } private string _viewModel; public string ViewModel { get { return _viewModel; } set { _viewModel = value; InitializeViewModel(); } } protected override void OnLoad(EventArgs e) { InitializeViewModel(); InitializeBindingProperties(this); base.OnLoad(e); } private void InitializeViewModel() { if (ViewModelState == null && !String.IsNullOrWhiteSpace(this.ViewModel)) { var viewModelAssemblyName = this.ViewModel; var assmebly = Assembly.LoadWithPartialName(viewModelAssemblyName); while (assmebly == null) { if (viewModelAssemblyName.LastIndexOf('.') <= 0) break; viewModelAssemblyName = viewModelAssemblyName.Remove(viewModelAssemblyName.LastIndexOf('.')); assmebly = Assembly.LoadWithPartialName(viewModelAssemblyName); } if (assmebly == null) return; var vm = assmebly.CreateInstanceOf<INotifyPropertyChanged>(this.ViewModel); if (vm != null) { vm.PropertyChanged += ViewModelPropertyChanged; } this.ViewModelState = vm; } } private void InitializeBindingProperties(Control control) { if (control is IAttributeAccessor) { var value = (control as IAttributeAccessor).GetAttribute("Binding"); var bindings = BindingProperty.TryParse(value); if (bindings != null) { bindingProperties.Add(control, bindings); ApplyChanges(control); } } control.Controls.OfType<Control>().ToList().ForEach(item => InitializeBindingProperties(item)); } private void ViewModelPropertyChanged(object sender, PropertyChangedEventArgs e) { this.ApplyBindings(e.PropertyName); } public void ActionCommand(object sender, CommandEventArgs e) { this.ApplyCommand(e.CommandName); } private void ApplyChanges(Control control) { if (bindingProperties.Any(item => Object.Equals(item.Key, control)) == false) return; var bindingsControl = bindingProperties.FirstOrDefault(item => Object.Equals(item.Key, control)); foreach (var binding in bindingsControl.Value) { var controlProperty = control.GetType().GetProperty(binding.Property); var viewModelProperty = ViewModelState.GetType().GetProperty(binding.Path); if (controlProperty != null && viewModelProperty != null) { var value = controlProperty.GetValue(control); var valueType = viewModelProperty.PropertyType; try { viewModelProperty.SetValue(ViewModelState, Convert.ChangeType(value, valueType)); } catch { var defaultValue = valueType.Assembly.CreateInstance(valueType.FullName); viewModelProperty.SetValue(ViewModelState, defaultValue); } } } } private void ApplyBindings(string propertyName) { if (bindingProperties.Any(item => item.Value.Any(var => var.Path == propertyName)) != true) return; var bindingsControl = bindingProperties.FirstOrDefault(item => item.Value.Any(var => var.Path == propertyName)); var control = bindingsControl.Key; var binding = bindingsControl.Value.FirstOrDefault(item => item.Path == propertyName); var controlProperty = control.GetType().GetProperty(binding.Property); var viewModelProperty = ViewModelState.GetType().GetProperty(binding.Path); if (controlProperty != null && viewModelProperty != null) { var value = viewModelProperty.GetValue(ViewModelState); controlProperty.SetValue(control, String.Format(binding.Format, value)); } } private void ApplyCommand(string commandName) { if (ViewModelState != null) { var method = ViewModelState.GetType().GetMethod(commandName); if (method != null) { method.Invoke(ViewModelState, new object[0]); } } } } }
Microsoft Community Contributor
-
-
Rui já tinha visto algo parecido, acho que o legal talvez é criar um framework e hospedar no codeplex ou no github
Não esqueça de usar o componente </> na barra para posta seu código. Microsoft MCPD,MCTS,MCC
Entao... essa era ideia... mas to totalmente sem tempo de tocar isso... eu vi o ASP.NET MVVM mas usando o MVC... acho que um nao combina com o outro ja que o legal do MVVM é deixar a View pro designer...
Vou entrar em ferias semana q vem se consegui um tempo monto algo no CodePlex
Microsoft Community Contributor
-
Ok... estou subindo uma versão no CodePlex... quem tiver interesse favor entrar em contato...
Aproveitei e dei uma melhorada... fiz alguns testes e me pareceu bem promissor isso:
https://webformmvvm.codeplex.com/
um exemplo de como ficou a View:
<%@ Page Language="C#" Inherits="Nomad.ASPMVVM.PageView" ViewModel="ASP.MVVM.ViewModel.TesteViewModel" %> <%@ Import Namespace="Nomad.ASPMVVM" %> <!DOCTYPE html> <script runat="server"> private BindingProperty ValorProperty = new BindingProperty { Property = "Text", Path = "Valor" }; private BindingProperty ResultadoProperty = new BindingProperty { Property = "Text", Path = "Resultado", Format = "{0:#,##0.00}" }; private BindingProperty OperacoesProperty = new BindingProperty { Property = "DataSource", Path = "Operacoes", NeedsBind = true }; private BindingProperty OperacaoSelecionadaProperty = new BindingProperty { Property = "SelectedValue", Path = "OperacaoSelecionada" }; private BindingProperty CalcularCommand = new BindingProperty { Path = "Calcular", IsCommand = true }; </script> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title></title> </head> <body> <form id="form1" runat="server"> <asp:ScriptManager runat="server" /> <asp:UpdatePanel runat="server"> <ContentTemplate> <p> <asp:TextBox runat="server" Binding='<%# Eval(ValorProperty) %>' /> <asp:DropDownList runat="server" Binding='<%# Eval(OperacoesProperty, OperacaoSelecionadaProperty) %>' /> <asp:Button Text="Calcular" runat="server" Binding='<%# Eval(CalcularCommand) %>' /> </p> <p> <asp:Label runat="server" Binding='<%# Eval(ResultadoProperty) %>' /> </p> </ContentTemplate> </asp:UpdatePanel> </form> </body> </html>
Microsoft Community Contributor