Stavo osservando this question e ho scoperto che il binding da Label.Content
a un valore non stringa applicherà uno stile implicito TextBlock
, tuttavia il binding a una stringa non lo è.Perché viene applicato uno stile TextBlock implicito quando si associa Label.Content a una non stringa, ma non a una stringa?
Ecco alcuni esempi di codice per riprodurre il problema:
<Window.Resources>
<Style TargetType="Label">
<Setter Property="FontSize" Value="26"/>
<Setter Property="Margin" Value="10"/>
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="FontSize" Value="26"/>
<Setter Property="Margin" Value="10"/>
</Style>
</Window.Resources>
<Grid>
<StackPanel Orientation="Horizontal">
<Label Content="{Binding SomeString}" Background="Red"/>
<Label Content="{Binding SomeDecimal}" Background="Green"/>
</StackPanel>
</Grid>
dove il codice per i valori legati vengono
SomeDecimal = 50;
SomeString = SomeDecimal.ToString();
E il risultato finale è come questo, con la proprietà Margin
dalla implicita Stile TextBlock applicato all'etichetta vincolato solo a una stringa:
Entrambe le etichette vengono resi come
<Label>
<Border>
<ContentPresenter>
<TextBlock />
</ContentPresenter>
</Border>
</Label>
Quando controllo il VisualTree con Snoop, posso vedere che sembra esattamente lo stesso per entrambi gli elementi, ad eccezione del 2 ° TextBlock si applica il margine dallo stile implicita, mentre il primo no.
ho usato Miscela di tirare fuori una copia del modello di etichetta di default, ma non vedo niente di strano, e quando applico il modello per entrambi i miei etichette, la stessa cosa accade.
<Label.Template>
<ControlTemplate TargetType="{x:Type Label}">
<Border BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
Padding="{TemplateBinding Padding}"
SnapsToDevicePixels="True">
<ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}"
Content="{TemplateBinding Content}"
ContentStringFormat="{TemplateBinding ContentStringFormat}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Label.Template>
Va inoltre notato che l'impostazione di un valore predefinito ContentTemplate
ad un TextBlock
non fare entrambe le voci rendono senza lo stile implicita, quindi deve avere qualcosa a che fare con quando WPF cerca di rendere un valore non stringa come parte dell'interfaccia utente.
<Window.Resources>
<Style TargetType="Label">
<Setter Property="FontSize" Value="26"/>
<Setter Property="Margin" Value="10"/>
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
<Style x:Key="TemplatedStyle" TargetType="Label" BasedOn="{StaticResource {x:Type Label}}">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="{Binding }"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="FontSize" Value="26"/>
<Setter Property="Margin" Value="10"/>
</Style>
</Window.Resources>
<Grid>
<StackPanel Orientation="Horizontal">
<Label Content="{Binding SomeString}" Background="Red"/>
<Label Content="{Binding SomeDecimal}" Background="Green"/>
<Label Content="{Binding SomeString}" Background="Red"
Style="{StaticResource TemplatedStyle}"/>
<Label Content="{Binding SomeDecimal}" Background="Green"
Style="{StaticResource TemplatedStyle}"/>
</StackPanel>
</Grid>
Qual è la logica che causa una non stringa inserita nella UI da trarre utilizzando uno stile TextBlock implicita, ma una stringa inserita l'interfaccia utente non lo fa? E dove avviene questo?
Questa domanda mi ha incuriosito, quindi ho dovuto iniziare il vecchio riflettore. Beh, c'è solo una cosa che potrei trovare finora. Sembra che TextBlock faccia una distinzione tra testo semplice e oggetti "complessi", utilizza due sottoclassi differenti per entrambi. Purtroppo questo è dove finisce. Non riesco a trovare alcuna traccia di uno stile specializzato o altro. Una cosa da provare è fornire un ContentTemplate con un TextBlock e controllare se questo cambia qualcosa. In tal caso potrebbe avere qualcosa a che fare con quel modello mistico predefinito. – dowhilefor
@dowhilefor Ho provato a estrarre il modello predefinito da Blend e applicarlo a entrambe le etichette, e succede la stessa cosa (domanda aggiornata con quelle informazioni). La mia unica ipotesi sarebbe che WPF sappia rendere un 'System.String' come un' TextBlock' senza uno stile implicito, ma quando va a renderizzare un valore non-string, lo disegna come un 'TextBlock' legato a' .ToString() 'dell'oggetto e applica qualsiasi stile implicito. – Rachel
@dowhilefor Hai ragione però che l'impostazione predefinita di 'ContentTemplate' su a' 'rende entrambi gli oggetti renderizzati senza lo stile implicito, quindi sembra che abbia qualcosa a che fare con il default 'ContentTemplate' per oggetti non stringa –
Rachel