首先,还是需要一个Model类来为UI层的元素提供数据源
public class LoginModel:DependencyObject { public string Uid { get { return (string)GetValue(UidProperty); } set { SetValue(UidProperty, value); } } // Using a DependencyProperty as the backing store for Uid. This enables animation, styling, binding, etc... public static readonly DependencyProperty UidProperty = DependencyProperty.Register("Uid", typeof(string), typeof(LoginModel), null); public string Pwd { get { return (string)GetValue(PwdProperty); } set { SetValue(PwdProperty, value); } } // Using a DependencyProperty as the backing store for Pwd. This enables animation, styling, binding, etc... public static readonly DependencyProperty PwdProperty = DependencyProperty.Register("Pwd", typeof(string), typeof(LoginModel),null ); public ICommand LoginCmd { get { return new LoginCommand(); } } }
<pre name="code" class="csharp">public class LoginCommand:ICommand { public bool CanExecute(object parameter) { return true; } public void Execute(object parameter) { LoginModel login = (LoginModel) parameter; if (login.Uid == "admin" && login.Pwd == "111") { MessageBox.Show("ok"); } else { MessageBox.Show("error"); } } public event EventHandler CanExecuteChanged; }
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="14,10,10,-10" Grid.ColumnSpan="2" DataContext="{StaticResource loginModel}"> <TextBox Name="txtUid" Text="{Binding Uid,Mode=TwoWay}" HorizontalAlignment="Left" Height="72" Margin="115,35,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="224"/> <TextBox Name="txtPwd" Text="{Binding Pwd,Mode=TwoWay}" HorizontalAlignment="Left" Height="72" Margin="115,138,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="224"/> <TextBlock Text="账号:" HorizontalAlignment="Left" Margin="28,60,0,0" TextWrapping="Wrap" VerticalAlignment="Top" RenderTransformOrigin="-0.146,-0.259"/> <TextBlock Text="密码:" HorizontalAlignment="Left" Margin="28,163,0,0" TextWrapping="Wrap" VerticalAlignment="Top" RenderTransformOrigin="-0.146,-0.259"/> <Button Content="登陆" Command="{Binding LoginCmd}" CommandParameter="{Binding}" HorizontalAlignment="Left" Margin="28,246,0,0" VerticalAlignment="Top"/> </Grid>
启动调试,点击按钮进行判断,完美运行
但是肯定是有地方不对劲
那到底是哪里的问题?
仔细想想mvvm的原则
在xaml.cs后台不直接操作UI元素
Model提供数据源
UI元素绑定数据源
LoginCommand的Execute方法进行业务逻辑处理
其实在前面的Execute方法的业务处理代码中已经违反了mvvm的规定
public void Execute(object parameter) { LoginModel login = (LoginModel) parameter; if (login.Uid == "admin" && login.Pwd == "111") { MessageBox.Show("ok"); } else { MessageBox.Show("error"); } }这里只能写逻辑处理的代码
不能有控制UI的部分
上面这么写就相当于asp.net的三层中在Bll层突然来了个Response.Redirect一样
这很明显是不允许的!
那么要如何修改呢?
首先
既然对MessageBox明确了不能出现在这里
那么只能在xaml.cs后台文件中进行处理了
那么后台又不能包含有任务业务处理的代码
他怎么才能知道什么时候要Show一下信息,然后Show什么信息呢?
这就要用到一个事件机制了
先定义一个委托
public delegate void LoginResult(bool success);
然后在LoginModel中定义一个事件
public event LoginResult LoginCompelete;
private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e) { LoginModel model = (LoginModel)this.Resources["loginModel"]; model.LoginCompelete += new LoginResult(model_LoginCompelete); } void model_LoginCompelete(bool success) { if (success) { MessageBox.Show("ok!"); } else { MessageBox.Show("error!"); } }
既然在页面加载的时候 就已经为LoginModel的LoginCompelete事件添加完了显示MessageBox的方法
那么在Execute中需要做的事情就只是 判断用户的账号密码
然后根据结果触发这个事件就ok了
但是因为事件本质是一个私有的委托+add和remove两个属性
所以该事件只能在内部被触发
所以在LoginModel中需要提供一个方法,让外界能够通过该方法触发LoginCompelete事件
public void FirLoginCompelete(bool success) { if (LoginCompelete != null) { LoginCompelete(success); } }
public void Execute(object parameter) { LoginModel login = (LoginModel) parameter; if (login.Uid == "admin" && login.Pwd == "111") { login.FirLoginCompelete(true); } else { login.FirLoginCompelete(false); } }