1
  • 我有一个用户名和密码框。
  • 在它下面我有一个按钮。
  • 当我单击该按钮时,我想分析已放入用户名和密码框中的内容。

如何使用 mvvm light 做到这一点?

这就是我所在的位置:

XAML

...DataContext="{Binding Main, Source={StaticResource Locator}}">...
    <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0">
        <TextBlock HorizontalAlignment="Left" Margin="10,0,0,0" TextWrapping="Wrap" Text="Username" VerticalAlignment="Top"/>
        <TextBox HorizontalAlignment="Left" Height="72" Margin="0,27,0,0" TextWrapping="Wrap" Text="{Binding Username}" VerticalAlignment="Top" Width="456"/>
        <TextBlock HorizontalAlignment="Left" Margin="10,99,0,0" TextWrapping="Wrap" Text="Password" VerticalAlignment="Top"/>
        <PasswordBox HorizontalAlignment="Left" Height="72" Margin="0,126,0,0" Password="{Binding Password}" VerticalAlignment="Top" Width="456"/>

        <Button Content="Log in" HorizontalAlignment="Center" Margin="167,203,169,0" VerticalAlignment="Top" Command="{Binding LogInCommand}"/>
    </Grid>

查看模型

public class MainViewModel : ViewModelBase
{
    public LoginCredentials LoginCredentials { get; set; }        
    public ICommand LogInCommand { get; private set; }

    public MainViewModel()
    {
        LoginCredentials = new LoginCredentials();
        LogInCommand = new RelayCommand(this.OnLogInCommand);
    }

    private void OnLogInCommand()
    {
        string testUsername = Username;
        string testPassword = Password;
    }

    #region Properties
    public string Username
    {
        get { return LoginCredentials.Username; }
        set { LoginCredentials.Password = value; }
    }
    public string Password
    {
        get { return LoginCredentials.Password; }
        set { LoginCredentials.Password = value; }
    }
    #endregion
}

MainPage.xaml.cs

public partial class MainPage : PhoneApplicationPage
{
    public MainPage()
    {
        InitializeComponent();
    }
}

目前正在发生的事情:

  • 当我单击我的按钮时,LogInCommand运行并触发我的方法OnLoginCommand。我在 testUsername 声明上放了一个断点,以查看单击按钮时,用户名和密码是否反映了输入的内容;他们都是空的。我必须怎么做才能确保在有人打字或按下按钮时更新这些内容,或者它可以工作???

我现在花了大约 4 周的时间学习 mvvm 并尝试让一个简单的点击事件和绑定工作。这根本没有意义...... doh。谢谢你的帮助!

PS - MVVM light 对新手来说太混乱了吗?文档是如此..细节很简单。没有例子:(

4

2 回答 2

3

看法

Windows Phone 不包含“UpdateSourceTrigger=PropertyChanged”。您必须在后面的代码中使用“ Explicit ”并手动调用“ UpdateSource ”,否则当 TextBox/PasswordBox 失去焦点时,TextBox/PasswordBox 的值将被提升。

并且不要忘记设置“ Mode=TwoWay ”。

<TextBox
    Text="{Binding Path=Username, Mode=TwoWay, UpdateSourceTrigger=Explicit}"
    TextChanged="TextBoxTextChanged" />

<PasswordBox
    Password="{Binding Path=Password, Mode=TwoWay, UpdateSourceTrigger=Explicit}"
    PasswordChanged="PasswordBoxPasswordChanged" />

<Button
    Command="{Binding Path=LogInCommand}"
    Content="Log in" />

查看 - 后面的代码

private void PasswordBoxPasswordChanged(object sender, RoutedEventArgs e)
{
    PasswordBox pb = sender as PasswordBox;

    if (pb != null)
    {
        pb.GetBindingExpression(PasswordBox.PasswordProperty).UpdateSource();
    }
}


private void TextBoxTextChanged(object sender, TextChangedEventArgs e)
{
    TextBox tb = sender as TextBox;

    if (tb != null)
    {
        tb.GetBindingExpression(TextBox.TextProperty).UpdateSource();
    }
}

视图模型

字段

private RelayCommand _logInCommand;
private string _password;
private string _username;

特性

public bool CanExecuteLogInCommand
{
    get
    {
        return !string.IsNullOrWhiteSpace(this.Username) && !string.IsNullOrWhiteSpace(this.Password);
    }
}

    public RelayCommand LogInCommand
    {
        get
        {
            // or you can create instance in constructor: this.LogInCommand = new RelayCommand(this.ExecuteLogInCommand, () => this.CanExecuteLogInCommand);
            return this._logInCommand ?? (this._logInCommand = new RelayCommand(this.ExecuteLogInCommand, () => this.CanExecuteLogInCommand));
        }
    }

    public string Username
    {
        get { return this._username; }

        set
        {
            // a) shorter alternative -> "True if the PropertyChanged event has been raised, false otherwise"
            if (this.Set(() => this.Username, ref this._username, value))
            {
                // raise CanExecuteLogInCommand
                this.LogInCommand.RaiseCanExecuteChanged();
            }


            // b) longer alternative
            //if (value == this._username) { return; }

            //this._username = value;

            //this.RaisePropertyChanged(() => this.Username);
            //this.LogInCommand.RaiseCanExecuteChanged();
        }
    }

    public string Password
    {
        get { return this._password; }

        set
        {
            if (this.Set(() => this.Password, ref this._password, value))
            {
                this.LogInCommand.RaiseCanExecuteChanged();
            }
        }
    }

方法

    private void ExecuteLogInCommand()
    {
        // .... = this.Username;
        // .... = this.Password;
    }

检查这个样本

于 2013-10-08T09:14:17.313 回答
0

要使 View 和 ViewModel “链接起来”以使它们同步,您需要实现 INotifyPropertyChanged(封装在 ViewModelBase 中)。IE:

private string userName;
public string UserName
{
    get { return userName; }
    set
    {
        if (value != userName)
        {
            userName = value;
            RaisePropertyChanged("UserName");
        }
    }
}
于 2013-10-08T01:36:35.977 回答