天天看點

WPF Binding學習(二)

  Binding作為資料的橋梁,連通業務邏輯層的對象(源對象)和UI的控件對象(目标對象)。在這座橋梁上,我們不僅可以控制在源對象與目标對象是雙向通行還是單向通行。還可以控制資料的放行時機,甚至可以在這座橋上搭建一些關卡用來轉換資料類型或者檢驗資料的正确性

   我們先做一個最基本的例子,

   建立一個"Student"類,這個類的執行個體将作為資料源來使用

public class Student
    {
        private int _id;

        public int ID
        {
            get { return _id; }
            set { _id = value; }
        }
        private string _name;

        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }

        private int _age;

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

    }      

  然後我們編寫我們的控件對象和建立邏輯對象

<StackPanel Name="stack1">
        <TextBox Width="120" Text="{Binding Path=ID}" HorizontalAlignment="Left" Name="txt_ID"></TextBox>
        <TextBox  Width="120" Text="{Binding Path=Name}" HorizontalAlignment="Left" Name="txt_Name" ></TextBox>
        <TextBox  Text="{Binding Path=Age}" Width="120" HorizontalAlignment="Left" Name="txt_Age"></TextBox>
   </StackPanel>      
public Student Stu; 
        public MainWindow()
        {
            InitializeComponent();
            Stu = new Student { ID = 1, Name = "狗娃", Age = 11 };
       //設定元素資料綁定對象
            stack1.DataContext = Stu;
        }      

 我們可以看到TextBox控件的Text是一個{Binding} 這就是資料綁定的關鍵字。然後Path屬性是需要綁定的屬性,然後我們運作就可以看到我們已經綁定OK。

 上面我們是使用的界面進行綁定,其實我們還可以使用代碼對每一個控件進行綁定。現在我們将WPF界面中的綁定删除掉

<StackPanel Name="stack1">
        <TextBox Width="120"  HorizontalAlignment="Left" Name="txt_ID"></TextBox>
        <TextBox  Width="120"  HorizontalAlignment="Left" Name="txt_Name" ></TextBox>
        <TextBox  Width="120" HorizontalAlignment="Left" Name="txt_Age"></TextBox>
    </StackPanel>      

 然後我們使用代碼來進行控件綁定

public Student Stu; 
  public MainWindow()
  {
            InitializeComponent();
            Stu = new Student { ID = 1, Name = "狗娃", Age = 11 };
            //建立Binding對象.
            Binding bindingID = new Binding() {Path = new PropertyPath("ID"),Source=Stu };
            //Binding構造參數可以直接傳入Path參數
            Binding bindingName = new Binding("Name") { Source = Stu };
            Binding bindingAge = new Binding("Age") { Source = Stu };

            //進行控件綁定(第一個參數是将綁定到哪個屬性,第二個參數是綁定對象)
            this.txt_ID.SetBinding(TextBox.TextProperty, bindingID);
            this.txt_Name.SetBinding(TextBox.TextProperty, bindingName);
            this.txt_Age.SetBinding(TextBox.TextProperty,bindingAge);
   }      

  可以看到使用代碼綁定需要建立Binding對象,然後使用控件的SetBinding方法進行綁定,但是郁悶的我們為了綁定這三個屬性要寫這麼多的代碼.是以使用哪種方式綁定看需求來使用.

 接下來我們看雙向綁定,其實上面那個我們已經實作了雙向綁定,我們先做一個例子測試

  建立一個測試TextBox并綁定資料ID

<TextBox Width="120"  HorizontalAlignment="Left"  Name="txt_IDTest"></TextBox>      
Binding bindingTestID = new Binding() { Path = new PropertyPath("ID"), Source = Stu };
 this.txt_IDTest.SetBinding(TextBox.TextProperty, bindingTestID);      

   然後我們在更改txt_ID屬性值後光标離開就可以看到txt_IDTest的值也随之改變了。這是因為TextBox預設是雙向綁定的,是以可以改變,但是如果我們不是使用控件改變的值呢,接下來做個這樣例子.在界面上添加一個Button按鈕,并添加點選事件

<Button Content="Button" Width="120" HorizontalAlignment="Left" Click="Button_Click"/>      
private void Button_Click(object sender, RoutedEventArgs e)
        {

            Stu.ID++;
        }      

我們在點選事件中隻做了一件事,那就是讓Stu的編号加1,但是運作會發現并沒有改變。那麼該怎麼做呢。

 我們需要在綁定源類型(Student類型)實作INotifyPropertyChanged接口

public class Student:INotifyPropertyChanged
    {
        private int _id;

        public int ID
        {
            get { return _id; }
            set { _id = value; MyPropertyChanged(nameof(ID)); }
        }

        private string _name;

        public string Name
        {
            get { return _name; }
            set { _name = value; MyPropertyChanged(nameof(Name)); }
        }

        private int _age;

        public event PropertyChangedEventHandler PropertyChanged;

        public int Age
        {
            get { return _age; }
            set { _age = value; MyPropertyChanged(nameof(Age)); }
        }
        private void MyPropertyChanged(string name)
        {
           if(PropertyChanged!=null)
                PropertyChanged(this, new PropertyChangedEventArgs(name));
        }
    }      

然後此時我們就可以實作改變了.

2.綁定更新的計時

但是我們往往需要在輸入後就讓它立即改變,是以我們需要設定Binding對象中的UpdateSourceTrigger屬性,

Binding bindingID = new Binding() { Path = new PropertyPath("ID"), Source = Stu, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged};      

 UpdateSourceTrigger枚舉值有4個

  • Default:綁定目标屬性的預設值
  • PropertyChanged:每當綁定目标屬性發生改變時,都會更新資料源
  • LostFocus:每當綁定目标元素失去焦點時,都會更新綁定源
  • Explicit:僅在調用System.Windows.Data.BindingExpression.UpdateSource 方法時更新綁定源。

   是以我們将UpdateSourceTrigger的屬性值改成PropertyChanged即可

  3.設定單項和雙向綁定

   剛才使用了TextBox的雙向綁定,但是比如我們現在不需要雙向綁定,我們隻需設定Mode屬性即可

Binding bindingID = new Binding() { Path = new PropertyPath("ID"), Source = Stu,Mode = BindingMode.OneTime, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged};      

 BindingMode枚舉有5個值

  • TwoWay:導緻更新源屬性或目标屬性時自動更新另一方
  • OneWay:在更改綁定源(源)時更新綁定目标(目标),如果綁定的控件為隐式隻讀,則此類型的綁定适用。如果無需監視目标屬性的更改  則使用 System.Windows.Data.BindingMode.OneWay 綁定模式可避免 System.Windows.Data.BindingMode.TwoWay

    綁定模式的系統開銷。

  • OneTime:這是實質上是 System.Windows.Data.BindingMode.OneWay 綁定的一種簡化形式,它在源值不更改的情況下提供更好的性能。
  • OneWayToSource:在目标屬性更改時,更新源屬性。
  • Default: 使用綁定目标的預設 System.Windows.Data.Binding.Mode 值