WPF数据绑定无法获取数据

时间:2014-03-19 11:13:07

标签: c# wpf data-binding

我正在使用 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

无论如何,这是一个演示,我必须在我的项目中使用数据绑定。我的代码出了什么问题?

3 个答案:

答案 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"));
                }
            }
        }
    }
}