引出問題
我們先用一個簡單的例子引出問題:有一個DateTime資源,分別用TextBox,Label顯示這個DateTime。
<Grid>
<Grid.Resources>
<sys:DateTime x:Key="DateTime001">03/29/2012 15:05:30</sys:DateTime>
</Grid.Resources>
<TextBox Text="{Binding Source={StaticResource DateTime001},StringFormat=dddd , Mode=OneWay}"
Height="23" HorizontalAlignment="Left" Margin="28,68,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" />
<Label Content="{Binding Source={StaticResource DateTime001}, StringFormat=dddd, Mode=OneWay}"
Height="28" HorizontalAlignment="Left" Margin="28,26,0,0" Name="label1" VerticalAlignment="Top" Width="120" />
</Grid>
運行結果如圖:
TextBox按照預期的,顯示了完整的英文星期,但是Label的格式沒有任何改變。我們用了完全一樣的Binding和格式字符串,區別究竟在什么地方?如果夠細心的話可以發現,TextBox的Binding是在Text屬性上進行的,而Label的Binding是在Content屬性上進行的。
詳細分析
本質原因:Control.Content是Object類型,而Binding.StringFormat僅僅在Binding的Property類型為string的時候才有效。
通過下面Label的Binding流程(來源於Stackoverflow牛人),我們可以看到底層的細節:
1. Binding把DateTime類型的值裝箱,賦值給Label.Content.
2. Label的Template包含ContentPresenter,用來顯示內容。
3. Label的ContentPresenter會會依次尋找ContentTemplate,DataTemplate去顯示內容,當而這都沒有找到的時候,它會用默認的Template。
4. ContentPresenter使用的默認Template用Label.ContentStringFormat屬性去格式化object到string。
5. 注意,以上是簡化的流程,本質的,ContentPresenter會用自身的Template和StringFormat顯示結果,但是由於在Label控件裝載過程中,會自動把Label的ContentTemplate和ContentStringFormat對應綁定到ContentPresenter的ContentTemplate和StringFormat。ContentPresenter本質會優先用Label的ContentTemplate和ContentStringFormat顯示。所以,我們這里說CotentPresenter用Label的Properties做顯示也沒有問題。
所以,對於非String類型的Content來說,添加屬性定義ContentStringFormat=dddd就可以顯示我們需要的結果了。