Как передать два параметра в EventToCommand - PullRequest
1 голос
/ 07 августа 2011

У меня следующий код 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 как поле одного объекта User

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

Ответы [ 2 ]

1 голос
/ 07 августа 2011

Обычно я бы просто сказал ... вам не нужно, поскольку ваша ViewModel (выведенная из ваших привязок) должна содержать как свойство User, так и команду Login iself, так что вы просто может получить доступ к свойству User из метода Excecute вашей команды.

Однако я заметил, что пользовательский класс, представленный в представленном вами пользовательском классе, не реализует INotifyPropertyChanged. Поэтому привязка не будет работать правильно. Чтобы это работало, у вас есть две возможности:

  1. Реализуйте INotifyPropertyChanged в своем пользовательском классе. - В зависимости от вашей модели и того, как она генерируется, это не всегда возможно.
  2. Дублируйте свойства вашей ViewModel и реализуйте INotifyPropertyChanged там. - Если у вас нет контроля над определением вашей модели (например, как оно генерируется прокси-сервером веб-службы), это единственный способ сделать это. Но даже если у вас есть контроль над вашей моделью, этот вариант стоит рассмотреть, поскольку он дает вам больший контроль над тем, что передается вашему представлению.

Итак, в следующем примере предполагается, что вы выберете второй вариант:

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, чтобы он соответствовал этой модели представления:

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

Обычно вам нужно использовать CommandParameter, только если вы находитесь внутри шаблона данных (например, шаблон элемента внутри ListBox) и / или ваша команда и ваши свойства не находятся в одном и том же ViewModel. В этом случае вы должны определить свою команду для принятия параметра:

#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; так что если у вас есть класс User со свойствами Email / Password в вашей ViewModel, то невозможно создать новый класс пользователя со свойствами Login / Password из XAML и передать его в вашу ViewModel. Привязка сильна, но не всемогуща ...; -)

0 голосов
/ 08 августа 2011

Поскольку ваши tbLogin.Text и tbPassword.Text двусторонне связаны с User.Email и User.Password соответственно, вы можете просто привязать CommandParameter к пользователю. Большой вопрос: зачем вам вообще нужен CommandParameter, тогда ваша модель представления может напрямую обращаться к свойству пользователя?

...