注册/登录

聊聊 Wpf 数据绑定实例

系统 Windows
监听事件机制,界面改变有TextChanged之类的事件,所以改变界面可以同步修改到对象。

[[381643]]

数据绑定的基本步骤:

(1)先声明一个类及其属性

(2)初始化类赋值

(3)在C#代码中把控件DataContext=对象;

(4)在界面设计里,控件给要绑定的属性{Binding 绑定类的属性}

原理:监听事件机制,界面改变有TextChanged之类的事件,所以改变界面可以同步修改到对象

想让普通对象实现数据绑定,需要实现INotifyPropertyChanged接口才能监听ProperChanged。具体代码如下显示:

  1. class Person:INotifyPropertyChanged 
  2.     { 
  3.         private int age; 
  4.   
  5.         public int Age 
  6.         { 
  7.             get 
  8.             { 
  9.                 return age; 
  10.             } 
  11.             set 
  12.             { 
  13.                 this.age = value; 
  14.                 if (PropertyChanged != null
  15.                 { 
  16.                    PropertyChanged(this, 
  17.                        new PropertyChangedEventArgs("Age")); 
  18.                 } 
  19.             } 
  20.         } 

BindingMode枚举值

MainWindow.xaml

  1. <Window x:Class="WpfApp1.MainWindow" 
  2.         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  3.         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
  4.         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
  5.         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
  6.         xmlns:local="clr-namespace:WpfApp1" 
  7.         mc:Ignorable="d" 
  8.         Title="MainWindow" Height="600" Width="800"
  9.     <StackPanel> 
  10.         <TextBlock Text="Student ID:" FontWeight="Bold" Margin="5"/> 
  11.         <TextBox Name="textBoxId" Margin="5" Text="{Binding Id,Mode=TwoWay}"/> 
  12.         <TextBlock Text="Student Name:" FontWeight="Bold" Margin="5"/> 
  13.         <TextBox Name="textBoxName" Margin="5" Text="{Binding Name,Mode=TwoWay}"/> 
  14.         <TextBlock Text="Student List:" FontWeight="Bold" Margin="5"/> 
  15.         <ListBox Name="listBox1" Height="110" Margin="5" > 
  16.             <ListBox.ItemTemplate> 
  17.                 <DataTemplate> 
  18.                     <StackPanel Orientation="Horizontal"
  19.                         <TextBlock Text="{Binding Path=Id}" Width="30"/> 
  20.                         <TextBlock Text="{Binding Path=Name}" Width="60"/> 
  21.                         <TextBlock Text="{Binding Path=Age}" Width="30"/> 
  22.                     </StackPanel> 
  23.                 </DataTemplate> 
  24.             </ListBox.ItemTemplate> 
  25.         </ListBox> 
  26.         <ListBox Name="listBox2"  Height="80" ItemsSource="{Binding Student}" DisplayMemberPath="Id" Margin="5"/> 
  27.         <Slider Name="slider1" MinHeight="25" Value="{Binding Id}"/> 
  28.         <Grid> 
  29.             <Grid.RowDefinitions> 
  30.                 <RowDefinition Height="*"></RowDefinition> 
  31.             </Grid.RowDefinitions> 
  32.             <Grid.ColumnDefinitions> 
  33.                 <ColumnDefinition Width="*"/> 
  34.                 <ColumnDefinition Width="*"/> 
  35.             </Grid.ColumnDefinitions> 
  36.             <Button Grid.Column="0" Content="Action" FontSize="40" Name="btnCtrl1" Height="80" Margin="5" Click="BtnCtrl1_Click"/> 
  37.             <Button Grid.Column="1" Content="Action" FontSize="40" Name="btnCtrl2" Height="80" Margin="5" Click="BtnCtrl2_Click"/> 
  38.         </Grid> 
  39.     </StackPanel> 
  40. </Window> 

首先解释下C#中的Task.Delay()和Thread.Sleep()

  • Thread.Sleep()是同步延迟,Task.Delay()是异步延迟。
  • Thread.Sleep()会阻塞线程,Task.Delay()不会。
  • Thread.Sleep()不能取消,Task.Delay()可以。
  • Task.Delay()实质创建一个运行给定时间的任务,Thread.Sleep()使当前线程休眠给定时间。
  • 反编译Task.Delay(),基本上讲它就是个包裹在任务中的定时器。
  • Task.Delay()和Thread.Sleep()最大的区别是Task.Delay()旨在异步运行,在同步代码中使用Task.Delay()是没有意义的;在异步代码中使用Thread.Sleep()是一个非常糟糕的主意。通常使用await关键字调用Task.Delay()。
  • 我的理解:Task.Delay(),async/await和CancellationTokenSource组合起来使用可以实现可控制的异步延迟。
  • MainWindow.xaml.cs

    1. using System; 
    2. using System.Collections.ObjectModel; 
    3. using System.ComponentModel; 
    4. using System.Threading.Tasks; 
    5. using System.Windows; 
    6.  
    7. namespace WpfApp1 
    8.     /// <summary> 
    9.     /// MainWindow.xaml 的交互逻辑 
    10.     /// </summary> 
    11.     public partial class MainWindow : Window 
    12.     { 
    13.         public ObservableCollection<Student> stuList; 
    14.         public MainWindow() 
    15.         {          
    16.             InitializeComponent(); 
    17.             this.DataContext = new Student() { Name="111", Id =1 }; 
    18.             Task.Run(async() =>  //开启异步线程task 
    19.             { 
    20.                 await Task.Delay(3000); //延时3秒 
    21.                 Dispatcher.Invoke((Action)delegate //线程中主界面显示需要用委托,不然这次赋值,在界面不更新 
    22.                 { 
    23.                     this.DataContext = new Student() { Name = "222", Id = 2 }; 
    24.                 }); 
    25.             });           
    26.             this.DataContext = new Student() { Name = "333" , Id = 3 }; 
    27.         } 
    28.  
    29.         private void BtnCtrl1_Click(object sender, RoutedEventArgs e) 
    30.         { 
    31.             Student stu = new Student() { Id = 4, Name = "Jon", Age = 29 }; //实例化一个Student类 并给类成员赋值 
    32.             this.DataContext = stu;//将实例化得对象传给DataContext 
    33.         } 
    34.         private void BtnCtrl2_Click(object sender, RoutedEventArgs e) 
    35.         { 
    36.             ObservableCollection<Student> stuList = new ObservableCollection<Student>() //具有通知属性的list 
    37.             { 
    38.              new Student() { Id=5, Name="Tim", Age=29 }, 
    39.              new Student() { Id=6, Name="Tom", Age=28 }, 
    40.              }; 
    41.             this.listBox1.ItemsSource = stuList; 
    42.  
    43.             this.listBox2.ItemsSource = stuList; 
    44.             this.listBox2.DisplayMemberPath = "Name"
    45.             this.DataContext = stuList; 
    46.         } 
    47.     } 
    48.     public class Student : INotifyPropertyChanged  //创建一个继承自INotifyPropertyChanged的类Student 
    49.     { 
    50.  
    51.         private string name
    52.  
    53.         public string Name 
    54.         { 
    55.             get { return name; } 
    56.             set 
    57.             { 
    58.                 name = value; 
    59.                 if (this.PropertyChanged != null
    60.                 { 
    61.                     PropertyChanged(this, new PropertyChangedEventArgs("Name")); //给Name绑定属性变更通知事件 
    62.                 } 
    63.             } 
    64.         } 
    65.  
    66.         private int id; 
    67.  
    68.         public int Id 
    69.         { 
    70.             get { return id; } 
    71.             set 
    72.             { 
    73.                 id = value; 
    74.                 if (this.PropertyChanged != null
    75.                 { 
    76.                     this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Id"));//给Id绑定属性变更通知事件 
    77.                 } 
    78.             } 
    79.         } 
    80.  
    81.         private int age; 
    82.  
    83.         public int Age 
    84.         { 
    85.             get { return age; } 
    86.             set 
    87.             { 
    88.                 age = value; 
    89.                 if (this.PropertyChanged != null
    90.                 { 
    91.                     this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Age"));//给Age绑定属性变更通知事件 
    92.                 } 
    93.             } 
    94.         } 
    95.  
    96.         public int ID { get; internal set; } 
    97.  
    98.         public event PropertyChangedEventHandler PropertyChanged; 
    99.     } 

    本文转载自微信公众号「CSharp编程大全」,可以通过以下二维码关注。转载本文请联系CSharp编程大全公众号。

    责任编辑:武晓燕 CSharp编程大全
    点赞
    收藏