WPF實例秀——不用屬性也Binding
正文:
實際編程中,由於咱們較多地使用到Binding類的Source與Path,因此可能會有一個思惟定式,那就是:有可能做爲數據源的類必定要準備好一些屬性,這些屬性將做爲Binding的Path。
若是本着這個思想去設計有可能做爲數據源的類,那麼會有兩個問題出現:
1. 這個類的哪些屬性有可能做爲數據源的Path?是都須要激發NotifyPropertyChanged事件,仍是用到了再添加?這頗有可能讓這個類遲遲不能封閉。
2. 須要用屬性把一些方法包裝起來,用來暴露給Binding,形成冗餘和語義上的不美觀。
其實,WPF類庫裏有一個名爲ObjectDataProvider的類就是專門爲了解決這個矛盾的——有了這個類,你在設計本身的類的時候就沒必要總想着把它設計成數據源的事兒了,該怎麼抽象就怎麼抽象、該怎麼封裝就怎麼封裝。
你可能會問:「若是這個類已經封閉了(再也不改動)而我又須要拿它當數據源了,碰巧所須要的數據是它某個方法的返回值,沒有對應屬性,怎麼辦?」OK,這就是ObjectDataProvider的用武之地了——使用它,能夠在你這個類的實例外面加上一層「包裝」(或者說是加個殼兒),使它變成一個標準的Binding數據源。
若是沒記錯的話,這應該是著名的「適配器模式」。
下面,咱們用一段簡單的代碼來學習如何使用ObjectDataProvider。
這個例子簡單到不能再簡單——三個TextBox,在前兩個裏輸入合適的數字,在第三個裏會顯示它們的和。按照UI與邏輯分開的原則,計算加法的功能應該由某個類來實現。
後臺負責計算的類是這樣:
- public class Calculator
- {
- public int Add(int arg1, int arg2)
- {
- return arg1 + arg2;
- }
-
- public string Add(string arg1, string arg2)
- {
- int x = 0;
- int y = 0;
- if (int.TryParse(arg1, out x) && int.TryParse(arg2, out y))
- {
-
- return this.Add(x, y).ToString();
- }
- else
- {
- return "Input Error!";
- }
- }
- }
你們看到了,設計這個類的時候,涉及到加法運算的邏輯時,任何一個程序員都會很天然地採用一個方法來實現,而不會爲了把它作成一個Binding的數據源專門把這些方法封裝進屬性裏——這樣就破壞了面向對象的抽象。
而後,讓咱們看看如何使用ObjectDataProvider來包裝這個類。
- <Window x:Class="WpfApplicationAdd.Window1"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:local="clr-namespace:WpfApplicationAdd"
- xmlns:system="clr-namespace:System;assembly=mscorlib"
- Title="Add" Height="136" Width="230" Background="SteelBlue">
- <Window.Resources>
- <ObjectDataProvider x:Key="odp" ObjectType="{x:Type local:Calculator}" MethodName="Add">
- <ObjectDataProvider.MethodParameters>
- <system:String>0</system:String>
- <system:String>0</system:String>
- </ObjectDataProvider.MethodParameters>
- </ObjectDataProvider>
- </Window.Resources>
- <StackPanel>
- <TextBox x:Name="textBox1" Margin="5" Text="{Binding Source={StaticResource odp}, Path=MethodParameters[0], BindsDirectlyToSource=true, UpdateSourceTrigger=PropertyChanged}" />
- <TextBox x:Name="textBox2" Margin="5" Text="{Binding Source={StaticResource odp}, Path=MethodParameters[1], BindsDirectlyToSource=true, UpdateSourceTrigger=PropertyChanged}"/>
- <TextBox x:Name="textBox3" Margin="5" Text="{Binding Source={StaticResource odp}, Mode=OneWay}"/>
- </StackPanel>
- </Window>
運行起來以後,你就能看到這樣的結果了: