WPF讓綁定支持表達式
部分代碼參考了CalcBinding
與之不同的是,我這個綁定有點兒花里胡哨,支持以下幾種綁定
<!--可以寫入簡單的代碼,但必須要完全限定名稱-->
<TextBlock Text="{e:Binding ElementName=window,Path='System.Convert.ToInt32((ActualWidth-2)*2.1)'}" />
<!--ViewModel中的計算-->
<TextBlock Text="{e:Binding Path=A+B/2+Person.Age}"
Background="Red"/>
<!--ViewModel與xaml混合計算-->
<Button Content="change"
x:Name="btn"
Command="{Binding ChangedCommand}"
Width="{e:Binding ElementName=window,Path='Width/2+B'}" />
<!--單獨綁定xaml-->
<TextBlock Text="{e:Binding ElementName=window}"
Width="{Binding ElementName=window,Path=Width}" />
<!--單獨綁定ViewModel-->
<TextBlock Text="{e:Binding Path=A}" />
但是有一點就是,不論是綁定viewmodel還是xaml,不支持設計時動態顯示,但支持運行時熱重載
同時支持例如三元表達式這樣的,如果覺得分割符號不夠的話,可以在屬性SymbolParameters中進行添加
git 源碼路徑
現在說下思路
創建一個綁定標記擴展
首先和CalcBinding一樣,將Binding的大部分屬性公開出來
在ProvideValue方法內部,先將Path屬性按運算符號進行分割出屬性列表
如果屬性列表小于2的話,則用使用單獨的Binding去綁定
反之則使用MultiBinding去綁定
特別注意的是MultiBinding中的,要判斷屬性列表是否以字母開頭,所以我這個綁定擴展綁定的屬性必須是以字母開頭的才可以綁定上
其次要注意在賦值ElementName的時候,要判斷當前屬性是否在當前Widnow的ElementName組件中是否存在,如果不存在,則不要賦值,它有可能是存在于ViewModel中
所以這里就是能將xaml屬性與ViewModel屬性進行混合綁定計算的關鍵了
然后就是在給MultiBinding賦值MultiValueConverter的時候,如果當前Window沒有,就不要賦值了,因為在設計時是沒有的,如果非要給,那么在設計時,會在Converter動態編譯的時候提示已經引入了相同的dll,然后整個設計器都全是堆棧錯誤,但是運行時還是好的
在MultiValueConverter的Convert方法中,循環判斷當前傳遞的值是否為錯誤值,是錯誤值的則不要,然后將每個屬性的正確類型查找出來
最后進行動態編譯內存程序集,同時將該方法和對象進行緩存,以便下次調用(不然每次都動態編譯會性能會很拉胯)
最后.
剛開始時我是使用JS引擎去解析數學表達式,在原始代碼中還有殘留,但后面發現,在解析例如 Person.Age 這類屬性時并不好處理,所以還是決定使用程序集動態編譯

浙公網安備 33010602011771號