如何通过数据绑定属性通知thingy mvvm light从文本框中获取文本

时间:2013-10-08 00:34:35

标签: c# windows-phone-8 mvvm-light

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

如何使用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。谢谢你的帮助!

P.S - MVVM对新来者来说太混乱了吗?文档是如此..详细说明。没有例子:(

2 个答案:

答案 0 :(得分:3)

查看

Windows Phone不包含“UpdateSourceTrigger = PropertyChanged”。您必须使用“显式”并在后面的代码中手动调用“ 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;
    }

选中 sample

答案 1 :(得分:0)

要使View和ViewModel'链接'以便它们被同步,您需要实现INotifyPropertyChanged(在ViewModelBase中封装)。即:

private string userName;
public string UserName
{
    get { return userName; }
    set
    {
        if (value != userName)
        {
            userName = value;
            RaisePropertyChanged("UserName");
        }
    }
}