如何将两个参数传递给EventToCommand

时间:2011-08-07 09:55:33

标签: silverlight windows-phone-7 mvvm-light

我有下一个xaml代码。

 <StackPanel Grid.Row="1" x:Name="spLogin">
            <TextBlock Text="E-mail:"></TextBlock>
            <TextBox Name="tbLogin" Text="{Binding User.Email, Mode=TwoWay}"></TextBox>
            <TextBlock Text="Password:"></TextBlock>
            <TextBox Name="tbPassword" Text="{Binding User.Password, Mode=TwoWay}"></TextBox>
            <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
                <Button Name="btnLogin" Content="Login">
                    <Interactivity:Interaction.Triggers>
                        <Interactivity:EventTrigger EventName="Click" 
                                            x:Name="SelectChangeEvent">
                            <Command:EventToCommand 
                            Command="{Binding Login, Mode=TwoWay}" PassEventArgsToCommand="False" CommandParameter="{Binding}"  />
                        </Interactivity:EventTrigger>
                    </Interactivity:Interaction.Triggers>
                </Button>
                <Button Name="btnClear" Content="Clear"/>
            </StackPanel>
        </StackPanel>
    </Grid>

如何将tbLogin.Text和tbPassword.Text作为一个对象的字段传递给ViewModel用户

public class User
{
    public string Login{get;set;}
    public string Password(get;set;)
}

2 个答案:

答案 0 :(得分:1)

通常我会说...你不需要,因为你的ViewModel(从你的绑定中推导出来)应该包含User属性和Login命令iself,这样您就可以从命令的User方法访问Excecute属性。

但是,我注意到您呈现的用户类的用户类没有实现INotifyPropertyChanged。因此,绑定将无法正常工作。为了使它有效,你有两种可能性:

  1. 在您的用户类上实施INotifyPropertyChanged。 - 根据您的型号及其生成方式,这并非总是如此。
  2. 复制ViewModel上的属性并在那里实现INotifyPropertyChanged。 - 如果您无法控制模型的定义(例如,由Web服务代理生成),这是执行此操作的唯一方法。但是,即使您可以控制您的模型,这个选项也值得考虑,因为您可以更好地控制传递给View的内容。
  3. 因此,以下示例假定您选择第二个选项:

    public class MvvmViewModel1 : ViewModelBase
    {
        private User _user;
    
        #region [Login]
    
        public const string LoginPropertyName = "Login";
    
        public string Login {
            get {
                return this._user.Login;
            }
    
            set {
                if (this._user.Login == value) {
                    return;
                }
    
                var oldValue = this._user.Login;
                this._user.Login = value;
    
                RaisePropertyChanged(LoginPropertyName);
            }
        }
    
        #endregion
    
        #region [Password]
    
        public const string PasswordPropertyName = "Password";
    
        public string Password {
            get {
                return this._user.Password;
            }
    
            set {
                if (this._user.Password == value) {
                    return;
                }
    
                var oldValue = this._user.Password;
                this._user.Password = value;
    
                RaisePropertyChanged(PasswordPropertyName);
            }
        }
    
        #endregion
    
        #region [LoginCommand]
    
        public RelayCommand _loginCommand;
    
        public RelayCommand LoginCommand {
            get {
                return _loginCommand ?? (_loginCommand = new RelayCommand(
                    () => {
                        // perform your login action here
                        // access Login with: this.Login
                        // access Password with: this.Password
                    },
                    () => {
                        // can execute method - sample implementation 
                        return (!string.IsNullOrEmpty(this.Login) && !string.IsNullOrEmpty(this.Password));
                    }
                ));
            }
        }
    
        #endregion
    }
    

    显然,你必须修改你的XAML以匹配这个ViewModel:

    <StackPanel Grid.Row="1" x:Name="spLogin">
        <TextBlock Text="E-mail:"></TextBlock>
        <TextBox Name="tbLogin" Text="{Binding Login, Mode=TwoWay}"></TextBox>
        <TextBlock Text="Password:"></TextBlock>
        <TextBox Name="tbPassword" Text="{Binding Password, Mode=TwoWay}"></TextBox>
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
            <Button Name="btnLogin" Content="Login">
                <Interactivity:Interaction.Triggers>
                    <Interactivity:EventTrigger EventName="Click" 
                                        x:Name="SelectChangeEvent">
                        <Command:EventToCommand 
                        Command="{Binding LoginCommand}" PassEventArgsToCommand="False"  />
                    </Interactivity:EventTrigger>
                </Interactivity:Interaction.Triggers>
            </Button>
            <Button Name="btnClear" Content="Clear"/>
        </StackPanel>
    </StackPanel>
    

    通常,如果您在数据模板内(例如ListBox中的项目模板)和/或您的命令并且您的属性不相同,则只需要使用CommandParameter视图模型。在这种情况下,您必须定义命令以接受参数:

    #region [LoginCommand]
    
    public RelayCommand _loginCommand;
    
    public RelayCommand LoginCommand {
        get {
            return _loginCommand ?? (_loginCommand = new RelayCommand(
                (p) => {
                    // perform your login action here
                },
                (p) => {
                    // can execute method - sample implementation 
                    return (!string.IsNullOrEmpty(this.Login) && !string.IsNullOrEmpty(this.Password));
                }
            ));
        }
    }
    
    #endregion
    

    现在你可以使用

    CommandParameter="{Binding}"
    

    在XAML中,将数据模板的数据上下文传递给ViewModel。

    另一方面说明:您通常不需要双向绑定 - 除非您想要将信息从View中写回ViewModel。

    另外作为旁注:你不能在XAML中生成/转换类;因此,如果您的ViewModel中有一个带有电子邮件/密码属性的User类,则无法在XAML中无法创建具有Login / Password属性的新用户类,并将其传递给ViewModel。绑定是强大但不​​是全部......; - )

答案 1 :(得分:0)

由于您的tbLogin.Text和tbPassword.Text双向绑定到User.Email和User.Password,因此您只需将CommandParameter绑定到User即可。更大的问题是:为什么你需要CommandParameter然后你的视图模型可以直接访问User属性?