【问题标题】:Windows Phone MVVM: Button Command Can Execute and Command ParamtereWindows Phone MVVM:按钮命令可以执行和命令参数
【发布时间】:2013-01-03 15:13:48
【问题描述】:

我想在这样的注册页面上实现 MVVM 模式:

页面有用户名、电子邮件和密码的文本框。

我想使用 ICommand 和 DelegateCommand 模式将注册按钮绑定到命令。

问题是如果文本框为空,我希望按钮被禁用,如果它们有文本则启用。

我的模特是:

public class User
    {
        public string UserName { get; set; }
        public string Email { get; set; }
        public string Password { get; set; }
    }

我的ViewModel:

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));
        }
}

我的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);
            }

        }



    }

和我的视图:

<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>

我想要实现的是禁用按钮,直到用户在每个 TextBox

中输入信息

如何做到这一点?

谢谢

【问题讨论】:

    标签: windows-phone-7 mvvm windows-phone-8 windows-phone


    【解决方案1】:

    第一件事:每次访问属性时返回一个新的DelegateCommand 将限制您调用RaiseCanExecuteChanged() 方法的能力,因为您不会引用绑定的相同命令。

    所以把你的 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 set 而无需调用 PropertyChanged 的​​原因,因为它将在绑定发生之前被实例化并且不需要更改。

    假设UserName和Password属性的形式触发了PropertyChanged事件,当它们发生变化时,您只需在RegisterCommand上调用RaiseCanExecuteChanged()方法即可。

    例如。

    private string _userName;
    public string UserName
    {
        get { return _userName; }
        set
        {
            if(_userName == value)
                return;
    
            _userName = value;
            RaisePropertyChanged("UserName");
    
            RegisterCommand.RaiseCanExecuteChanged();
        }
    }
    

    这将强制 CanExecute 方法重新评估。

    【讨论】:

    • 非常感谢,你拯救了我的一天 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-24
    • 1970-01-01
    • 1970-01-01
    • 2017-11-24
    • 2011-04-25
    • 2023-03-19
    • 1970-01-01
    相关资源
    最近更新 更多