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 這類屬性時並不好處理,所以還是決定使用程式集動態編譯