我正在使用 WPF 和 C#编写登录窗口,但在尝试从TextBox中检索用户名时卡住了。我绑定到TextBox的属性总是得到一个空值,我无法弄清楚原因。
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"));
}
}
}
}
}
我知道数据绑定在这种情况下不是明智的选择,只需使用
我就可以更有效地完成工作string Username = this.TextUsername.Text
无论如何,这是一个演示,我必须在我的项目中使用数据绑定。我的代码出了什么问题?
答案 0 :(得分:3)
在您附加绑定时,Login.Username
为空,并且由于绑定是双向的,WPF会将您的文本框更新为null以匹配。
绑定应该始终处于活动状态,并在XAML中声明,而不是绑定在您想要数据的点上。您正在击败使用绑定的对象。就像你说的那样,如果要明确地这样做,直接抓取文本要容易得多。
答案 1 :(得分:1)
问题是,当用户在Text
中输入/更改TextUsername
时,您的绑定还没有,(您的绑定只会在Confirm_Click
之后,并且会重置每个Confirm_Click
),所以你需要将它移动到构造函数。
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
}
}
您可以轻松地在XAML中应用绑定,并且如果您可以正确设置窗口的DataContext,则可以避免所有这些代码。例如:
<TextBox x:Name="TextUsername" Text="{Binding Username}" ..../>
答案 2 :(得分:0)
以下代码可以使用,不确定它是否是一个好习惯:
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"));
}
}
}
}
}