1.如果你需要資料跟UI元件能即時隨時的互動,隨著資料改變,UI的顯示就跟著變(或者反向),這時候,你就需要他。
2.如果你需要在Thread或Task中顯示目前進行的狀況或是任何資訊在某種UI元件上,比方Label, TextBlock,為了避免跨執行緒UI操作這種神秘又討厭的Exception,而你又不想為此作Delegate,這時候,你也可以靠他幫助。
在WPF上的作法有兩種,一種是把Bnding寫在 XML 裡,一種是寫在C#程式裡,差異不大,因為最後資料的顯示也都用程式在控制居多。
首先,建立一個WPF 應用程式專案,然後在視窗上放一個按鈕、一個TextBlock、一個TextBox。名稱Name分別取為Btn_Bind、TxtBlk_Bind、TxtBx_Bind。位置隨便你放,能看得到就好了。
接下來,在程式當中,新增一個繼承INotifyPropertyChanged的Class,並且給他一個Member(當然,如果你有多個元件要跟多組數值作Binding,這裡就可以有多個Member),固定寫法如下,當Member要寫入新值,在set當中呼叫OnPropertyChanged(),他會產生PropertyChangedEventHandler 的事件,因此可讓UI可以知道該更新顯示了。
public class MyData : INotifyPropertyChanged
{
private string m_TextMsg;
public string TextMsg
{
set
{
if ( m_TextMsg != value )
{
m_TextMsg = value;
OnPropertyChanged( "TextMsg" );
}
}
get
{
return m_TextMsg;
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged( string propertyName )
{
if ( PropertyChanged != null )
{
PropertyChanged( this, new PropertyChangedEventArgs( propertyName ) );
}
}
}
另外準備好按鈕的事件內容
private void Bind_Click( object sender, RoutedEventArgs e )
{
m_MyData.TextMsg = "New Value";
}
然後在CS檔中宣告一個全域變數,把你剛剛的INotifyPropertyChanged類型的Class宣告好
private MyData m_MyData ;
然後在程式進入點函式中加入底下,產生物件實體與給予初始值
m_MyData = new MyData();
m_MyData .TextMsg = "Origin";
以上都準備好之後,開始進行Binding
第一種方法:在XML加入Binding 片段
<TextBlock x:Name="TxtBlk_Bind" HorizontalAlignment="Center" Margin="134,130,136,140" TextWrapping="Wrap" VerticalAlignment="Center" Height="50" Width="247" FontSize="20" Text="{Binding Path=TextMsg }" TextAlignment="Center"/>
<TextBox x:Name="TxtBx_Bind" HorizontalAlignment="Left" Height="44" Margin="134,210,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="248" FontSize="20" Text="{Binding Path=TextMsg }"/>
<Button x:Name="Btn_Bind" Content="改變數值" HorizontalAlignment="Left" Height="37" Margin="134,62,0,0" VerticalAlignment="Top" Width="99" Click="Bind_Click"/>
最後用程式告訴系統,你的Binding是哪一個
TxtBlk_Bind.DataContext = m_BindData;
TxtBx_Bind.DataContext = m_BindData;
(能不能把上面兩段寫成XAML呢?其實是可以的,可是,寫來頗複雜,而且還不知道要怎麼讓CS引用這個變數)
如此,你的TxtBlk_Bind跟TxtBx_Bind兩個元件就跟m_BindData 內的TextMsg 有了互動
不相信?你可以按下按鈕,就會看到TxtBlk_Bind跟TxtBx_Bind元件都變成了"New Value",而如果你在TxtBx_Bind輸入任何文字,然後按下[Tab]鍵,就可以看到TxtBlk_Bind也會跟著變成你輸入的東西了。(這是因為TxtBx_Bind輸入的數值會同步變更BindData內的TextMsg 數值,然後在同步更新到TxtBlk_Bind元件。
第二種方法:完全在程式中完成Binding
XML不用改,只要在程式當中加上底下四行:
Binding BindingTxtBlk = new Binding() { Source = m_MyData , Path = new PropertyPath( "TextMsg" ) };
TxtBlk_Bind.SetBinding( TextBlock.TextProperty, BindingTxtBlk );
Binding BindingTxtBx = new Binding() { Source = m_MyData , Path = new PropertyPath( "TextMsg" ) };
TxtBx_Bind.SetBinding( TextBox.TextProperty, BindingTxtBx );
太棒了,對吧!
我喜歡第二種,因為不用動到XML,感覺也挺直覺的。
您好,我想用您第二種做法,
回覆刪除去替換此網站的sample
http://www.dotblogs.com.tw/ouch1978/archive/2011/07/29/wpf-globalization-xmldataprovider.aspx
請問可以做得到嗎?
若可以,麻煩可以提示一下要怎麼做嗎?
謝謝您。
應該就把我上面第二種作法的程式貼到MainWindow.xml.cs就好了
刪除但是事情準備工作:「以上都準備好之後,開始進行Binding」的那些準備工作應該還是要先寫好