【.net 深呼吸】實時獲取計算結果
上次老周介紹了在 UWP 應用中通過 x:Bind 標記來綁定到方法,以實現實時獲取計算結果。今天,咱們來耍耍WPF上面的實現方法。
雖然,WPF 沒有 x:Bind 標記(暫時沒有,以後不好說),但 WPF 在數據綁定方面也是有很強大的引擎D,畢竟它是 .net 框架一部分。其實,當年在 .net 1.x 的時候,老周就推測微軟會推出新的框架的,只是當時還不知道它叫 WPF,為啥呢。因為當時老周發現,Windows 窗體應用相關的類型都放在 System.Windows.Forms 命名空間下,不知道你初學.net 時會不會感到很奇怪,反正老周覺得很怪,為什麽不直接放到 System.Windows 命名空間下呢,所以,我就想到,System.Windows 命名空間下將來肯定要放別的東西。
後來,.net 2.0 SP1,.net 3.0,尤其是 .net 3.5 的時候,這個框架逐步定型,故我一直認為 4.0 是.net 成熟的標誌。
好了,不上歷史課了,咱們還是繼續上編程課吧。
在 WPF 中,提供了一種很好玩的綁定模型——DataSourceProvider,當然,它是抽象類,不能直接用的,直接用的話會抽風。它的派生類為我們實現了兩種形式的“間接綁定”:XmlDataProvider 可以組件或鏈接外部的XML文檔;ObjectDataProvider可以綁定到某個類型或該類型的實例對象,而且還可以綁定到類型的方法成員上,實例方法或是靜態方法皆可。
要實時獲取計算結果,應當使用 ObjectDataProvider 類,如果要綁定實例方法,除了要為 ObjectType 屬性設定目標類型的Type外,還要將該類型的實例賦給 ObjectInstance 屬性;如果是綁定到靜態方法,那就不必要指定 ObjectInstance 屬性了。
然後,通過 MethodName 屬性設置要綁定的方法的名字,如果方法有參數,向 MethodParameters 列表添加元素,有幾個參數就傳幾個值,元素的順序與方法參數的聲明一致即可。註意這個方法要有返回值,因為綁定目標要從該方法獲取計算結果的。
下面咱們用一個示例來說明一下。
首先,得聲明一個類,用來進行計算,我就用一個靜態方法吧,簡單方便。
public class Demo { public static double GetMin(double a, double b) { return Math.Min(a, b); } }
這個方法很簡單,幼兒園層次的,輸入兩個數值,返回其中較小的值。
然後,重點來了,在 XAML 文檔中聲明 ObjectDataProvider 實例。
<Grid.Resources> <local:StrAndDoubleConverter x:Key="cvt"/> <ObjectDataProvider x:Key="dprd" ObjectType="{x:Type local:Demo}" MethodName="GetMin"> <ObjectDataProvider.MethodParameters> <sys:Double>0</sys:Double> <sys:Double>0</sys:Double> </ObjectDataProvider.MethodParameters> </ObjectDataProvider> </Grid.Resources>
StrAndDoubleConverter 是一個自定義的轉換器,在 string 和 double 之間轉化,這個大家可以無視。
ObjectType 屬性指定的是我們剛剛定義的 Demo 類,MethodName 方法指定剛剛那個靜態方法。由於這個方法需要兩個輸入參數,所以,得向 MethodParameters 中添加兩個 double 值,默認全設為 0。
下面我們在 UI 上放兩個 TextBox 控件,用來輸入兩數值,並且當輸入的值改變時,自動把值傳遞到 ObjectDataProvider 對象的 MethodParameters 列表中。如何實現呢?數據綁定,把 TextBox 的 Text 屬性與 MethodParameters 中的元素進行綁定,並且是雙向綁定。
<TextBox Grid.Row="0" Grid.Column="1" Margin="4" Text="{Binding Source={StaticResource dprd},BindsDirectlyToSource=True,Mode=TwoWay,Path=MethodParameters[0],Converter={StaticResource cvt},UpdateSourceTrigger=PropertyChanged}"/> <TextBox Grid.Row="1" Grid.Column="1" Margin="4" Text="{Binding Source={StaticResource dprd},BindsDirectlyToSource=True,Mode=TwoWay,Path=MethodParameters[1],Converter={StaticResource cvt},UpdateSourceTrigger=PropertyChanged}"/>
此處, BindsDirectlyToSource 屬性記得要設置為 true,這個是啥意思呢?它的意思就是,這個Binding是直接綁定到 Source 屬性所指定的對象,還是原始數據源。在本例這個綁定模型中,原始數據源應為 Demo 類,而中間數據源是 ObjectDataProvider 對象,因此,如果不把 BindsDirectlyToSource 屬性設置為true,那麽這個 Binding 所相對的是 Demo 類,如果 BindsDirectlyToSource 屬性為 true,那麽該Binding的相對源就會指向 ObjectDataProvider 對象,這樣一來,Path 屬性才能找到 MethodParameters 列表中的元素。
其中,[0] 表示列表中的第一個元素,即傳給綁定方法的第一個參數,同理,[1] 就是指向第二個參數。為了能夠在 Text 屬性更改時更新方法參數,需要設置 UpdateSourceTrigger=PropertyChanged,Mode=TwoWay。
接著,我們聲明一個 TextBlock 元素,同樣也是綁定到前面在資源中聲明的 ObjectDataProvider 對象上,實時獲取計算的結果。
<TextBlock Grid.Row="1" Margin="5"> <Run Text="較小的那個數:"/> <Run Text="{Binding Source={StaticResource dprd},Mode=OneWay}" Foreground="DarkGreen" FontSize="18"/> </TextBlock>
這裏只需要讀取結果即可,所以,Mode 為 OneWay 即可。如果計算需要花較長時間,可以設置 IsAsynchronous 屬性為 true,這樣可以優化 UI 的響應速度。
好了,示例完成了,咱們來看看運行效果吧。
而後,老周嘗試把方法的返回值改為 void,以 out 和 ref 方式進行計算結果賦值,但綁定後不能獲得正確的結果。
示例源代碼下載請點擊這裏。
【.net 深呼吸】實時獲取計算結果