1

I am writting a login window using WPF and C#,but got stuck when I attempted to retrive username from the TextBox.The class property which I bind to the TextBox always get a null value,and I cannot figure out why.

MainWindow.xaml

<Window x:Class="Databinding.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="256*"/> <ColumnDefinition Width="261*"/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="*"/> <RowDefinition Height="*"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <Label Grid.Row="0" Grid.Column="0" Content="Username" HorizontalAlignment="Stretch" Margin="0,0,0,0" VerticalAlignment="Stretch" HorizontalContentAlignment="Right" VerticalContentAlignment="Center" FontSize="20"/> <Label Grid.Row="1" Grid.Column="0" Content="Password" HorizontalAlignment="Stretch" Margin="0,0,0,0" VerticalAlignment="Stretch" HorizontalContentAlignment="Right" VerticalContentAlignment="Center" FontSize="20"/> <Button Content="Confirm" Click="Confirm_Click" IsDefault="True" Grid.Row="2" Grid.Column="0" HorizontalAlignment="Stretch" Margin="0,0,0,0" VerticalAlignment="Stretch" FontSize="20"/> <Button Content="Cancel" Click="Cancel_Click" IsCancel="True" Grid.Row="2" Grid.Column="1" HorizontalAlignment="Stretch" Margin="0,0,0,0" VerticalAlignment="Stretch" FontSize="20"/> <TextBox x:Name="TextUsername" Grid.Row="0" Grid.Column="1" HorizontalAlignment="Stretch" Margin="0,0,0,0" TextWrapping="Wrap" VerticalAlignment="Stretch" ToolTip="Enter your username"/> <PasswordBox x:Name="Password" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Stretch" Margin="0,0,0,0" VerticalAlignment="Stretch" ToolTip="Enter your password"/> </Grid> 

MainWindow.xaml.cs

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.ComponentModel; namespace Databinding { /// <summary> /// MainWindow.xaml 的交互逻辑 /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void Confirm_Click(object sender, RoutedEventArgs e) { Login LoginInfo = new Login(); Binding bindingLogin = new Binding(); bindingLogin.Source = LoginInfo; bindingLogin.Path = new PropertyPath("Username"); bindingLogin.Mode = BindingMode.TwoWay; bindingLogin.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged; BindingOperations.SetBinding(this.TextUsername, TextBox.TextProperty, bindingLogin); if(LoginInfo.Username=="admin" && this.Password.Password=="admin") { MessageBox.Show("Welcome!","Login Status"); } else { MessageBox.Show("Something is wrong!","Login Status"); } } private void Cancel_Click(object sender, RoutedEventArgs e) { this.Close(); } } public class Login:INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; private string username; public string Username { get { return username; } set { username = value; if(this.PropertyChanged!=null) { this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Username")); } } } } } 

I know databinding is not a wise option in this case,and I can get things done more efficently by just using

string Username = this.TextUsername.Text 

Anyway,this is a some demo,and I have to use databinding in my project.What's wrong with my code?

3
  • How do you access that UserName property and from where ? Commented Mar 19, 2014 at 11:17
  • 1
    Why is databinding not a wise option? It is THE way to solve this. Password fields are not databound. Commented Mar 19, 2014 at 11:19
  • Why you even try to bind on click? Commented Mar 19, 2014 at 11:23

3 Answers 3

3

At the point you attach your binding, Login.Username is null, and since the binding is two way WPF will update your textbox to null to match.

Bindings are supposed to be active all the time, and declared in the XAML, rather than bound at the point you want data. You are defeating the object of using bindings. Like you say, it would be far easier to just grab the text directly if you are going to do it explicitly.

Sign up to request clarification or add additional context in comments.

Comments

1

The problem is when user entering/changing Text in the TextUsername, your binding is not there yet, (your binding will only be there after the Confirm_Click, and will be reset with each Confirm_Click) so you need to move it to the constructor.

namespace Databinding { public partial class MainWindow : Window { Login LoginInfo; public MainWindow() { InitializeComponent(); LoginInfo = new Login(); Binding bindingLogin = new Binding(); bindingLogin.Source = LoginInfo; bindingLogin.Path = new PropertyPath("Username"); bindingLogin.Mode = BindingMode.TwoWay; bindingLogin.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged; BindingOperations.SetBinding(this.TextUsername, TextBox.TextProperty, bindingLogin); } //... rest } } 

And you could easily apply the binding in XAML, and avoid all of these code behind if you can set the DataContext of your window correctly e.g.:

<TextBox x:Name="TextUsername" Text="{Binding Username}" ..../> 

1 Comment

You've pointed out the problem exactly.But the above XAML code which creates data binding does not seem to work.Should I put it in the window resource?
0

The below code will works, not sure if it's a good practice thou:

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.ComponentModel; namespace Databinding { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { Login LoginInfo; Binding bindingLogin; public MainWindow() { InitializeComponent(); LoginInfo = new Login(); bindingLogin = new Binding(); bindingLogin.Source = LoginInfo; bindingLogin.Path = new PropertyPath("Username"); bindingLogin.Mode = BindingMode.TwoWay; bindingLogin.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged; } private void Confirm_Click(object sender, RoutedEventArgs e) { BindingOperations.SetBinding(this.TextUsername, TextBox.TextProperty, bindingLogin); if(LoginInfo.Username=="admin" && this.Password.Password=="admin") { MessageBox.Show("Welcome!","Login Status"); } else { MessageBox.Show("Something is wrong!","Login Status"); } } private void Cancel_Click(object sender, RoutedEventArgs e) { this.Close(); } } public class Login:INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; private string username; public string Username { get { return username; } set { username = value; if(this.PropertyChanged!=null) { this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Username")); } } } } } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.