前言 作為一隻菜鳥,之前學了一段時間的WPF,但是沒有總結,過了一學期發現好多東西都忘記了,很多東西還是需要記下來,以備後續複習。 數據綁定在事件中應用非常廣泛,可以有效地減少代碼量,那麼什麼是數據綁定?說的簡單就是從源對象提取一些信息,將其用於設置目標對象的屬性,這裡有一點需要註意,目標屬性需要是
前言
作為一隻菜鳥,之前學了一段時間的WPF,但是沒有總結,過了一學期發現好多東西都忘記了,很多東西還是需要記下來,以備後續複習。
數據綁定在事件中應用非常廣泛,可以有效地減少代碼量,那麼什麼是數據綁定?說的簡單就是從源對象提取一些信息,將其用於設置目標對象的屬性,這裡有一點需要註意,目標屬性需要是依賴屬性(Dependency Property),而源對象可以是任何內容。
數據綁定可以分為元素到元素的綁定和元素到非元素對象的綁定。
元素到元素綁定
XAML綁定
首先來看一個簡單的例子
<Grid> <Grid.RowDefinitions> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> </Grid.RowDefinitions> <Slider Name="sldFontSize" Minimum="8" Maximum="36" VerticalAlignment="Center"></Slider> <TextBlock Grid.Row="1" Name="txbSampleText" FontSize="{Binding ElementName=sldFontSize, Path=Value, Mode=TwoWay}" HorizontalAlignment="Center">示例文本</TextBlock> </Grid>
通過改變滑動條的值可以改變文本值,這裡使用了XAML來進行數據綁定,ElementName=sldFontSize 表示綁定的源對象為上面的滑動條,Path=Value 表示源對象的屬性為滑動條的值,Mode=TwoWay 表示使用雙向綁定。這裡有四種綁定模式
BindingMode的枚舉值
OneWay |
當源屬性變化時更新目標屬性 |
TwoWay |
當源屬性變化時更新目標屬性,並且當目標屬性變化時更新源屬性 |
OneTime | 最初根據源屬性值設置目標屬性,然後後續其它改變均被忽略。必要時可以減少開銷 |
OneWayToSource |
與OneWay相同,但是方向相反 |
Default |
此類綁定依賴於目標屬性,既可以雙向,也可以是單向,為預設值 |
使用雙向綁定需要更大的開銷,所以一般需要合理選擇綁定模式。
代碼綁定
在XAML標記中使用Binding標記拓展來聲明綁定表達式最為高效,但是有時候我們仍然需要使用代碼來創建綁定
Binding bd = new Binding(); bd.Source = sldFontSize; bd.Path = new PropertyPath("Value"); bd.Mode = BindingMode.TwoWay; txbSampleText.SetBinding(FontSizeProperty, bd);
上述代碼完成的功能和用XAML創建是一樣的。但是明顯複雜不少,那麼在什麼時候需要使用代碼創建綁定呢
1.創建動態綁定:如果希望根據其他運行時信息修改綁定,或者根據環境創建不同的綁定,這時使用代碼創建綁定更合理。
2.刪除綁定:如果希望刪除綁定,從而通過普通方式設置屬性,可以使用ClearBinding()或ClearAllBinding()方法。
當然一個元素可以使用多個綁定
<Grid> <Grid.RowDefinitions> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> </Grid.RowDefinitions> <Slider Name="sldFontSize" Minimum="8" Maximum="36" VerticalAlignment="Center"></Slider> <TextBlock Grid.Row="1" Name="txbSampleText" FontSize="{Binding ElementName=sldFontSize, Path=Value, Mode=TwoWay}" Foreground="{Binding ElementName=txtForeground ,Path=Text}" HorizontalAlignment="Center">示例文本</TextBlock> <TextBox Grid.Row="2" Name="txtForeground" FontSize="{Binding ElementName=sldFontSize, Path=Value, Mode=TwoWay}" ></TextBox> </Grid>
截圖如下
同時綁定的時候還有何時更新的問題,大部分綁定更新都是在PropertyChanged時出發,但是應該註意TextBox.Text的預設方式是LostFocus.
PropertyChanged | 當目標屬性發生變化時立即更新源 |
LostFocus | 當目標屬性發生變化且目標丟失焦點時更新源 |
Explicit | 除非調用BindingExpression.UpdateSource()方法,否則不更新源 |
Default | 根據目標屬性的元數據確定更新行為(根據FrameworkPropertyMetadata.DefaultUpdateTrigger屬性) |
這裡也需要根據開銷合理選擇。
綁定延遲
如果需要在更新前暫停一會,可以添加短暫的延遲時間,避免過分頻繁的觸發操作,如在代碼中添加Delay=500,即可在用戶停止輸入500毫秒後更新源對象。
綁定到非元素對象
在數據驅動的程式中,使用更多的是創建從不可見對象中提取數據的綁定表達式,唯一的要求是希望顯示的信息必須存儲在公有屬性中,此時需要放棄Binding.ElementName屬性,轉而使用以下屬性之一
- Source:該屬性是指向源對象的引用
- RelativeSource:使用RelativeSource指向源對象,使用此附加層可在當前元素的基礎上構建引用。
- DataContext:如果沒有使用Source或RelativeSource屬性指定源,那麼WPF會從當前元素從元素樹上開始查找,檢查每個元素的DataContext屬性,並使用第一個非空的DataContext屬性
數據綁定在WPF技術中非常重要,下一篇文章中,我會對綁定到非元素對象進行更深入的介紹,敬請期待。
參考資料:WPF編程寶典-使用C#2012和.NET4.5(第四版)