【.NET深呼吸】(WPF)跨窗口完成綁定


在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。

 

示例源碼下載

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM