wpf应用程序中的简单数据绑定

时间:2015-06-04 05:46:15

标签: c# wpf data-binding 2-way-object-databinding

您好我正在尝试研究wpf中的简单数据绑定。我尝试过但没有成功..请提出方法..

<Window x:Class="WpfTestApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="250" Width="350">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="70"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="50"/>
            <RowDefinition Height="50"/>
            <RowDefinition Height="50"/>
            <RowDefinition Height="50"/>
        </Grid.RowDefinitions>

        <Label Content="First Name" Grid.Row="0" Grid.Column="0" Height="25" HorizontalAlignment="Stretch"/>
        <Label Content="Last Name" Grid.Row="1" Grid.Column="0" Height="25" HorizontalAlignment="Stretch"/>
        <Label Content="Full Name" Grid.Row="2" Grid.Column="0" Height="25" HorizontalAlignment="Stretch"/>

        <TextBox x:Name="fName" Text="{Binding FirstName, UpdateSourceTrigger=PropertyChanged}" Grid.Row="0" Grid.Column="1" Height="25" HorizontalAlignment="Stretch"/>
        <TextBox x:Name="lName" Text="{Binding LastName, UpdateSourceTrigger=PropertyChanged}" Grid.Row="1" Grid.Column="1"  Height="25" HorizontalAlignment="Stretch"/>
        <Label x:Name="lblFullName" Content="{Binding FirstName}" Grid.Row="2" Grid.Column="1" Height="25" HorizontalAlignment="Stretch"/>
        <Button x:Name="cmdCommand" Content="Command" Grid.Row="3" Grid.Column="1" Margin="2" VerticalAlignment="Center" HorizontalAlignment="Center" Click="cmdCommand_Click"/>
    </Grid>
</Window>

现在你看,我希望在文本框中输入名称时,标签lblFullName会自动更新。

现在我的codebehind文件看起来像这样:

  public partial class MainWindow : Window, INotifyPropertyChanged
    {
        private string _firstName;
        public string FirstName
        {
            get { return _firstName; }
            set
            {
                if (value != _firstName)
                {
                    _firstName = value;
                    OnPropertyChanged("FirstName");
                }
            }
        }

        private string _lastName;
        public string LastName
        {
            get { return _lastName; }
            set
            {
                if (value != _lastName)
                {
                    _lastName = value;
                    OnPropertyChanged("LastName");
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Notifies objects registered to receive this event that a property value has changed.
        /// </summary>
        /// <param name="propertyName">The name of the property that was changed.</param>
        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        public MainWindow()
        {
            InitializeComponent();
        }

        private void cmdCommand_Click(object sender, RoutedEventArgs e)
        {
            lblFullName.Content = FirstName + " " + LastName;
        }

    }

不用说,即使点击命令按钮也不起作用......

有什么建议吗?

1 个答案:

答案 0 :(得分:0)

将DataContext设置为指向窗口本身将解决当前问题:

public MainWindow()
{
    InitializeComponent();
    this.DataContext = this;
}

Xaml中Binding表达式中的路径都是相对于控件的DataContext的,因此必须设置DataContext。

但是,我强烈建议您将名字和姓氏放在一个单独的类中(例如 PersonViewModel ),这样可以使代码更易于阅读和维护。

public class PersonViewModel : INotifyPropertyChanged
{
    private string _firstName;
    public string FirstName
    {
        get { return _firstName; }
        set
        {
            if (value != _firstName)
            {
                _firstName = value;
                OnPropertyChanged("FirstName");
            }
        }
    }

    private string _lastName;
    public string LastName
    {
        get { return _lastName; }
        set
        {
            if (value != _lastName)
            {
                _lastName = value;
                OnPropertyChanged("LastName");
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        var handler = this.PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = new PersonViewModel();
    }

    private void cmdCommand_Click(object sender, RoutedEventArgs e)
    {
        lblFullName.Content = FirstName + " " + LastName;
    }
}

现在这段代码的最后一部分不再起作用了。有两种解决方案。

快速而肮脏的解决方案:

    private void cmdCommand_Click(object sender, RoutedEventArgs e)
    {
         var person = this.DataContext as PersonViewModel;
         if(person == null) return;
         lblFullName.Content = string.Format("{0} {1}", person.FirstName, person.LastName);
    }

更好的方法是,在尝试执行适当的MVVM时,在ViewModel中添加一个额外的属性(请注意First和Last名称属性的更改!):

public class PersonViewModel : INotifyPropertyChanged
{
    public string FullName
    {
        get 
        {
            return string.Format("{0} {1}", FirstName, LastName);
        }
    }

    private string _firstName;
    public string FirstName
    {
        get { return _firstName; }
        set
        {
            if (value != _firstName)
            {
                _firstName = value;
                OnPropertyChanged("FirstName");
                OnPropertyChanged("FullName");
            }
        }
    }

    private string _lastName;
    public string LastName
    {
        get { return _lastName; }
        set
        {
            if (value != _lastName)
            {
                _lastName = value;
                OnPropertyChanged("LastName");
                OnPropertyChanged("FullName");
            }
        }
    }
    // remainder of the class remains the same
}

删除按钮及其单击处理程序。将标签绑定到这个新属性:

<Label Content="{Binding FullName}" 
       Grid.Row="2" Grid.Column="1" 
       Height="25" HorizontalAlignment="Stretch"/>