Windows phone 7 Windows Phone MVVM:可以执行按钮命令和命令参数
我想将MVVM模式实现到如下注册页面:Windows phone 7 Windows Phone MVVM:可以执行按钮命令和命令参数,windows-phone-7,mvvm,windows-phone-8,windows-phone,Windows Phone 7,Mvvm,Windows Phone 8,Windows Phone,我想将MVVM模式实现到如下注册页面: public class UserViewModel : INotifyPropertyChanged { private User user; public UserViewModel() { user = new User(); RegisterCommand = new DelegateCommand(Register,CanRegister); } public DelegateCommand
public class UserViewModel : INotifyPropertyChanged
{
private User user;
public UserViewModel()
{
user = new User();
RegisterCommand = new DelegateCommand(Register,CanRegister);
}
public DelegateCommand RegisterCommand {get; private set;}
private void Register(object parameter)
{
//TODO call the web service
}
private bool CanRegister(object parameter)
{
return (!string.IsNullOrEmpty(UserName) &&
!string.IsNullOrEmpty(Password));
}
}
该页面有用户名、电子邮件和密码文本框
我想使用ICommand和DelegateCommand模式将Register按钮绑定到命令
问题是,如果文本框为空,我希望按钮被禁用,如果有文本,则按钮被启用
我的型号是:
public class User
{
public string UserName { get; set; }
public string Email { get; set; }
public string Password { get; set; }
}
我的视图模型:
public class UserViewModel:INotifyPropertyChanged
{
private User user;
public UserViewModel()
{
user = new User();
}
#region Properties
.
.
.
#endregion
public ICommand RegisterCommand
{
get
{
return new DelegateCommand(Register,CanRegister);
}
}
private void Register(object parameter)
{
//TODO call the web service
}
private bool CanRegister(object parameter)
{
return (!string.IsNullOrEmpty(UserName) && !string.IsNullOrEmpty(Password));
}
}
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="Username:"/>
<TextBox Grid.Row="1" Name="txtUserName" Text="{Binding UserName, Mode=TwoWay}" HorizontalAlignment="Stretch"/>
<TextBlock Grid.Row="2" Text="Password:" HorizontalAlignment="Stretch" />
<TextBox Grid.Row="3" Name="txtPassword" Text="{Binding Password, Mode=TwoWay}"/>
<Button Grid.Row="4" Content="Register" Command="{Binding RegisterCommand }" />
</Grid>
我的DelegateCommand实现:
public class DelegateCommand:ICommand
{
//Delegate to the action that the command executes
private Action<object> _executeAction;
//Delegate to the function that check if the command can be executed or not
private Func<object, bool> _canExecute;
public bool canExecuteCache;
public DelegateCommand(Action<object> executeAction):this(executeAction,null)
{
}
public DelegateCommand(Action<object> action, Func<object, bool> canExecute)
{
this._executeAction = action;
this._canExecute = canExecute;
}
//interface method, called when CanExecuteChanged event handler is fired
public bool CanExecute(object parameter)
{
//true by default (in case _canExecute is null)
bool result = true;
Func<object, bool> canExecuteHandler = this._canExecute;
if (canExecuteHandler != null)
{
result = canExecuteHandler(parameter);
}
return result;
}
//Event handler that the controld subscribe to
public event EventHandler CanExecuteChanged;
//interface method
public void Execute(object parameter)
{
_executeAction(parameter);
}
//rause the CanExecuteChanged event handler manually
public void RaiseCanExecuteChanged()
{
EventHandler handler = this.CanExecuteChanged;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
}
公共类DelegateCommand:ICommand
{
//委托给命令执行的操作
私人行动——执行;
//委托给检查命令是否可以执行的函数
私人职能执行;
公共图书馆;
公共DelegateCommand(Action executeAction):此(executeAction,null)
{
}
公共DelegateCommand(操作,Func canExecute)
{
这._executeAction=动作;
这个._canExecute=canExecute;
}
//接口方法,在触发CanExecuteChanged事件处理程序时调用
公共布尔CanExecute(对象参数)
{
//默认情况下为true(如果_canExecute为null)
布尔结果=真;
Func canExecuteHandler=这个;
如果(canExecuteHandler!=null)
{
结果=canExecuteHandler(参数);
}
返回结果;
}
//controld订阅的事件处理程序
公共事件处理程序CanExecuteChanged;
//接口方法
public void Execute(对象参数)
{
_执行(参数);
}
//手动使用CanExecuteChanged事件处理程序
public void raisecancecutechanged()
{
EventHandler=this.CanExecuteChanged;
if(处理程序!=null)
{
处理程序(此,EventArgs.Empty);
}
}
}
以及我的视图:
public class UserViewModel:INotifyPropertyChanged
{
private User user;
public UserViewModel()
{
user = new User();
}
#region Properties
.
.
.
#endregion
public ICommand RegisterCommand
{
get
{
return new DelegateCommand(Register,CanRegister);
}
}
private void Register(object parameter)
{
//TODO call the web service
}
private bool CanRegister(object parameter)
{
return (!string.IsNullOrEmpty(UserName) && !string.IsNullOrEmpty(Password));
}
}
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="Username:"/>
<TextBox Grid.Row="1" Name="txtUserName" Text="{Binding UserName, Mode=TwoWay}" HorizontalAlignment="Stretch"/>
<TextBlock Grid.Row="2" Text="Password:" HorizontalAlignment="Stretch" />
<TextBox Grid.Row="3" Name="txtPassword" Text="{Binding Password, Mode=TwoWay}"/>
<Button Grid.Row="4" Content="Register" Command="{Binding RegisterCommand }" />
</Grid>
我想要实现的是禁用按钮,直到用户在每个文本框中输入信息
如何做到这一点
谢谢首先要做一件事:每次访问属性时返回一个新的
DelegateCommand
将限制您调用RaiseCanceTechChanged()
方法的能力,因为您不会引用绑定的相同命令
因此,将您的ViewModel更改为类似以下内容:
public class UserViewModel : INotifyPropertyChanged
{
private User user;
public UserViewModel()
{
user = new User();
RegisterCommand = new DelegateCommand(Register,CanRegister);
}
public DelegateCommand RegisterCommand {get; private set;}
private void Register(object parameter)
{
//TODO call the web service
}
private bool CanRegister(object parameter)
{
return (!string.IsNullOrEmpty(UserName) &&
!string.IsNullOrEmpty(Password));
}
}
之所以可以将RegisterCommand
属性设置为private,而不需要PropertyChanged调用,因为它将在绑定发生之前实例化,不需要更改
假设属性UserName
和Password
的形式触发PropertyChanged
事件,当它们发生更改时,您只需调用RegisterCommand
上的raisecancecutechanged()
方法即可
例如
这将迫使CanExecute方法重新评估。非常感谢,你救了我一天:)