WPF---数据绑定(二)

一、绑定到非UI元素

上篇中,我们绑定的数据源均是派生自UIElement的WPF元素。本篇描述的绑定数据源是一个我们自定义的普通的类型。

注:尽管绑定的数据源可以是任意类型的对象,但Path必须总是指向一个公共属性。

当绑定一个非UI元素对象时,不能使用Binding.ElementName属性,但可以使用以下属性中的一个:

Source——该属性是指向源对象的引用,即提供数据的对象;

RelativeSource——该属性使用RelativeSource对象指定绑定源的相对位置,默认值为null;

DataContext属性——如果没有使用Source或RelativeSource属性指定一个数据源,WPF会从当前元素开始在元素树中向上查找,

检查每个元素的DataContext属性,并使用第一个非空的DataContext属性。当然你也可以自己设置DataContext属性。

下面我们模拟以下场景,左面的lable分别绑定我们自定义的类Person的Age和Name属性,右面我们可以动态的修改person中的Age和Name属性,当属性动态修改的时候,我们观察左面的lable中的文本信息是否发生变化。

参考代码如下:

using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;

namespace BindingDemo2
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private Person person;
        public Person Person
        {
            get { return person; }
            set { person = value; }
        }
        public MainWindow()
        {
            InitializeComponent();

            this.DataContext = this;

            person = new Person();

            Binding binding = new Binding("Age") { Source = person };
            lbAge.SetBinding(Label.ContentProperty, binding);

        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {   
            person.Age = Convert.ToInt32(tbAge.Text);
            person.Name = tbName.Text;
        }
    }
    public class Person
    {
        private int _age = 18;

        public int Age
        {
            get { return _age; }
            set
            {
                _age = value;
            }
        }

        private string _name = "Mary";
        public string Name
        {
            get { return _name; }
            set
            {
                _name = value;
            }
        }
        public Person()
        {
            Age = 18;
            Name = "Mary";
        }

    }

}
<Window x:Class="BindingDemo2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:BindingDemo2"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525" Name="win">
    <Grid ShowGridLines="True">
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <StackPanel>
            <Label Content="Target"/>
            <Label Content="Name"/>
            <Label Content="{Binding Person.Name}" Height="30" Background="AliceBlue" Name="lbName"/>
            <Label Content="Age"/>
            <Label  Height="30" Background="AliceBlue" Name="lbAge"/>
        </StackPanel>
        <StackPanel Grid.Column="1">
            <Label Content="Source"/>
            <Label Content="Name"/>
            <TextBox Height="30" Background="AliceBlue" Name="tbName" Text="Mary"/>
            <Label Content="Age"/>
            <TextBox Height="30" Background="AliceBlue" Name="tbAge" Text="18"/>
            <Button Content="Set" Click="Button_Click"></Button>
        </StackPanel>
    </Grid>
</Window>

运行结果如下:

 从结果可以发现,我们的绑定成功了。但是,当我们在右面修改Name和Age的时候,左面的lable中的文字信息却没有发生改变,这是为什么呢?

通过调试我们发现,点击Set按钮之后,person对象中的属性的确是改变了,但是由于属性改变没有通知binding,所以界面的UI没有更新。

为了可以通知binding属性修改了,我们对数据源Person类做如下修改:

   public class Person : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;

            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        private int _age = 18;

        public int Age
        {
            get { return _age; }
            set
            {
                _age = value;
                OnPropertyChanged("Age");
            }
        }

        private string _name = "Mary";

        public string Name
        {
            get { return _name; }
            set
            {
                _name = value;
                OnPropertyChanged("Name");
            }
        }
        public Person()
        {
            Age = 18;
            Name = "Mary";
        }

    }

如此一来,当person更新的时候,UI就会随着一起更新了。

原文地址:https://www.cnblogs.com/3xiaolonglong/p/9723542.html