標籤:tran 即時 res windows alt out com 方法參數 賦值
上次老周介紹了在 UWP app中通過 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] 表示列表中的第一個元素,即傳給Binder 方法的第一個參數,同理,[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 深呼吸】即時擷取計算結果