wpf XAML xaml 進行 數據綁定,Resource DataContext ElementName


先做個聲明:這里綁定都在前台實現,至於后台怎么寫,那比前台簡單多了,但更常用的是xaml中綁定。我們分析下最簡單的字符串綁定來弄清楚原理,其他的類推就是。

數據綁定主要是要弄清楚兩個東西,一個是源Source,一個是路徑Path。

什么能夠作為源Source呢:

CLR類型的單個對象

CLR類型的集合對象

DataTable和DataView

XML數據

依賴對象

FrameworkElement的DataContext

控件及ElementName

假如現在有一個最簡單的需求:有一個窗口MainWindow,它里面有一個文本框(TextBox),Name為textBox,文本框的內容(Text)要綁定一個字符串。

好了,現在我們要考慮一個上面需求沒提到的問題,該字符串是哪的字符串?

1.另外一個類Student(含公開屬性Name)的實例化對象對應的Name

在哪實例化這個類Student呢?

  • 在MainWindow.xaml.cs里,對不起,即使實例化了,xaml里無法直接訪問cs里的實例化的對象。
  • 在xaml里實例化,有個不錯的選擇就是通過聲明資源(Resource)
 1 <Grid>
 2         <Grid.Resources>
 3             <local:Student x:Key="stu" StuName="張三"/>
 4         </Grid.Resources>
 5         <TextBox Name="textBox"
 6                  Width="150"
 7                  Height="23"
 8                  BorderBrush="Black" 
 9                  Text="{Binding Source={StaticResource stu},Path=StuName}"/>
10 </Grid>

這種方法測試是可行的。

 

  • 那如果通過數據上下文DataContext的方式呢,怎么寫

DataContext只要存在於要綁定的控件的本身或者其邏輯樹父級以上就可以,我們還是定義在Grid上吧

 1 <Grid Name="grid">
 2         <Grid.DataContext>
 3             <local:Student StuName="李四"/>
 4         </Grid.DataContext>
 5         <TextBox Name="textBox"
 6                  Width="150"
 7                  Height="23"
 8                  BorderBrush="Black" 
 9                  Text="{Binding Path=StuName}"/>
10 </Grid>

這種方法測試也是可行的。

 

 

2.如果該字符串存在於當前頁面,是當前頁面的一個公開屬性呢

 1 public partial class MainWindow : Window
 2     {
 3         public MainWindow()
 4         {
 5             InitializeComponent();
 6         }
 7         private string str;
 8 
 9         public string Str
10         {
11             get
12             {
13                 return str;
14             }
15 
16             set
17             {
18                 str = value;
19             }
20         }
21     }
  • 我們先嘗試用資源實例化
 1 <Window.Resources>
 2         <local:MainWindow x:Key="str" Str="王五" />
 3     </Window.Resources>
 4     <Grid Name="grid">
 5         <TextBox Name="textBox"
 6                  Width="150"
 7                  Height="23"
 8                  BorderBrush="Black"
 9                  Text="{Binding Source={StaticResource str}, Path=Str}" />
10 </Grid>

啟動的時候報錯了:

原因是資源不允許嵌套,就是說頁面定義的資源不能是本身的實例。

  • 再試試DataContext
 1 <Grid Name="grid">
 2         <Grid.DataContext>
 3             <local:MainWindow Str="王五" />
 4         </Grid.DataContext>
 5         <TextBox Name="textBox"
 6                  Width="150"
 7                  Height="23"
 8                  BorderBrush="Black"
 9                  Text="{Binding Path=Str}" />
10 </Grid>

跟上面報了相同的錯,看來數據上下文也不能指定為自己的實例。

  • 那就沒招了嗎?有的,直接將整個窗口(它也是FrameworkElement)作為Source,通過指定ElementName的方式
 1 <Window x:Class="Binding.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:local="clr-namespace:Binding"
 6         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 7         Title="MainWindow"
 8         Width="525"
 9         Height="350"
10         mc:Ignorable="d"
11         Name="this">
12     <Grid Name="grid">
13         <TextBox Name="textBox"
14                  Width="150"
15                  Height="23"
16                  BorderBrush="Black"
17                  Text="{Binding ElementName=this, Path=Str}" />
18     </Grid>
19 </Window>

我們需要在cs里對Str賦值,否則綁定的是Str的默認值,這塊我們這樣理解,ElementName指定自己,那么就是實例化了一個MainWindow,它里面的屬性都是取的默認值。

我們在構造里寫 Str=“ZHAOLIU”,發現運行的文本框仍然為空,這是因為我們賦值是在界面初始化語句InitializeComponent();之后,

我們的屬性又不具備更改通知功能,所以改變了值也不會起作用。下面我們就改造為可更改通知的。只需要繼承接口INotifyPropertyChanged並實現他的約束就可以了。

 1 using System;
 2 using System.Collections.Generic;
 3 using System.ComponentModel;
 4 using System.Linq;
 5 using System.Text;
 6 using System.Threading.Tasks;
 7 using System.Windows;
 8 using System.Windows.Controls;
 9 using System.Windows.Data;
10 using System.Windows.Documents;
11 using System.Windows.Input;
12 using System.Windows.Media;
13 using System.Windows.Media.Imaging;
14 using System.Windows.Navigation;
15 using System.Windows.Shapes;
16 
17 namespace Binding
18 {
19     /// <summary>
20     /// MainWindow.xaml 的交互邏輯
21     /// </summary>
22     public partial class MainWindow : Window, INotifyPropertyChanged
23     {
24         public MainWindow()
25         {
26             InitializeComponent();
27             Str = "ZHAOLIU";
28         }
29         private string str;
30 
31         public event PropertyChangedEventHandler PropertyChanged;
32 
33         public string Str
34         {
35             get
36             {
37                 return str;
38             }
39 
40             set
41             {
42                 str = value;
43                 if (PropertyChanged != null)
44                 {
45                     PropertyChanged(this, new PropertyChangedEventArgs("Str"));
46                 }
47             }
48         }
49     }
50 }

 經過測試是可以的。

 

 

3.如果字符串存在於另一個窗口,是其一個公開屬性呢

我們再新建個窗口Window1

 1 public partial class Window1 : Window
 2     {
 3         public Window1()
 4         {
 5             InitializeComponent();
 6         }
 7         private string str;
 8 
 9         public string Str
10         {
11             get
12             {
13                 return str;
14             }
15 
16             set
17             {
18                 str = value;
19             }
20         }
21     }

然后我們在MainWindow里實例化Window1試試

 1 <Window.Resources>
 2         <local:Window1 x:Key="str" Str="王五" />
 3     </Window.Resources>
 4     <Grid Name="grid">
 5         <TextBox Name="textBox"
 6                  Width="150"
 7                  Height="23"
 8                  BorderBrush="Black"
 9                  Text="{Binding Source={StaticResource str}, Path=Str}" />
10 </Grid>

這是可以的。至此我們知道,資源中實例化一個對象,控件去綁定該對象的公開屬性,只要一條,該對象不能是自己本身就ok。

 

使用DataContext也是可以的

 1 <Window.DataContext>
 2         <local:Window1 Str="麻子"/>
 3     </Window.DataContext>
 4     <Grid Name="grid">
 5         <TextBox Name="textBox"
 6                  Width="150"
 7                  Height="23"
 8                  BorderBrush="Black"
 9                  Text="{Binding Path=Str}" />
10 </Grid>

ElementName呢,MainWindow拿不到Window1里的控件,就算你給Window1給了個名字,在MainWindow也不能以字符串直接拿到,不知道你們有沒有見過將控件的值綁定到另一個頁面的一個控件上的。

 

總結下: 

 

 

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM