在99.999975%的情形下,可視化元素之間的相互綁定都會在同一個容器中完成,如同一個窗口,同一個UserControl等。但在極少數的情況下,為了從最大限度減少代碼賦值的前提下考慮,是可以使用跨窗口綁定。
比如窗口A中有一個控件XA,B窗口中有個YB控件,我希望把A中的XA控件的Text屬性與B中的YB控件的Item屬性進行綁定。綁定后的好處在於,當Item屬性更新后,會自動修改Text屬性,而不需要額外寫代碼去監視各控件屬性的更改。因為高境界程序員向來都是以最少的代碼做最多的事情。
然而,在默認情況下,一個窗口的代碼是不能訪問另一個窗口中的控件的,XAML文檔中聲明的控件變量默認的訪問方式為private。為了解決這一局限,XAML的擴展標記中提供了FieldModifier擴展,可以修改XAML文檔中聲明對象的訪問方式。比如這樣:
<TextBlock Name="tbtxt" x:FieldModifier="public" />
通過設置x:FieldModifier="public",使得名為tbtxt的TextBlock控件會被生成為public字段,這么一來,其他的窗口就可以訪問該控件了。
只有解決了上述問題,才能實現控件的跨窗口綁定。
為了使本文的內容變得生動活潑,充滿青春活力,接下來老周會舉一個500年不遇的簡單例子。
本示例包含兩個窗口,主窗口為MainWindow類,外加一個自定義窗口MyDialog(當作自定義對話框)。主窗口中有一個TextBlock控件和一個Button控件,當點擊按鈕后會打開MyDialog對話框,對話框中有一個ComboBox控件,當用戶在ComboBox控件中選擇項時,會同步更新主窗口中TextBlock的顯示文本。
即,將MainWindow.TextBlock對象的Text屬性和MyDialog中的ComboBox控件的SelectedItem屬性進行綁定。Text屬性自動從SelectedItem屬性中取值。
為了讓MyDialog窗口能夠訪問主窗口中的TextBlock對象,所以XAML要這樣寫:
<TextBlock Name="tbtxt" x:FieldModifier="public" Margin="10"/> <Button Content="打開對話框" Click="OnOpenDialog"/>
然后,設計MyDialog的界面,聲明ComboBox對象,並添加幾個選項。
<ComboBox Name="cmb" > <sys:String>飛機</sys:String> <sys:String>坦克</sys:String> <sys:String>火車</sys:String> <sys:String>輪船</sys:String> <sys:String>大卡車</sys:String> <sys:String>拖拉機</sys:String> <sys:String>裝甲車</sys:String> </ComboBox> <Button HorizontalAlignment="Center" Grid.Row="1" Margin="0,20" Content="OK" Click="OnClick"/>
接着,在MyDialog類的構造函數中通過代碼來設置Binding。
public MyDialog(Window owner) { this.Owner = owner; InitializeComponent(); // 設置Binding對象 Binding b = new Binding(); b.Path = new PropertyPath(ComboBox.SelectedItemProperty); b.Source = cmb; b.Mode = BindingMode.OneWay; b.StringFormat = "您選擇的交通工具為:{0}"; MainWindow mw = Owner as MainWindow; // 使屬性與Binding關聯 mw?.tbtxt.SetBinding(TextBlock.TextProperty, b); }
Window類有一個Owner屬性,可以設置它的父窗口,這里,MyDialog作為彈出窗口,MainWindow作為父窗口,因此在實例化MyDialog時傳遞owner,使得代碼能訪問MainWindow。我這里為了方便省事,直接寫了個帶參數的構造函數。
注意此處的綁定,數據源是ComboBox控件,數據使用者是TextBlock,所以Binding的Source應為cmb實例,Path直接用依賴項屬性標識即可。
最后調用TextBlock對象的SetBinding方法就可以設置Binding了。
為啥不用XAML來binding呢,因為這是跨窗口的綁定,用XAML很難寫,用代碼來寫反而好處理。
運行程序,然后打開對話框,在對話框中選一個項,你會看到,父窗口中的顯示文本會自動更新。
准確地說,本文內容不算是什么高科技,純粹是一種技巧運用吧。示例不需要多復雜,只要能起到演示效果就行,老周天生討厭把事情復雜化,所以老周的座右銘是:
非Easy無以致學,非實戰無以Code。