How do the default color, font family and font size for a TextBlock and Label get set in an WPF app?
Solution 1
As far as I remember, in most cases classes like TextBlock
, TextBox
and many others take the text color from the TextElement.Foreground
property. The property value is inherited throughout the visual tree, i.e. you may set it on the root element and have most of the text change its color. For example:
<Grid TextElement.Foreground="Red">
<TextBlock Text="test"/>
</Grid>
In fact, the same is true even for labels: the setter in their default style simply sets the TextElement.Foreground
to one of the system colors.
However, this is true only for the default state of controls. Altered states, like highlighting, are not inherited, but rather taken from the system colors, as Rachel has written.
UPDATE
The same is true for FontSize
and FontFamily
. They are properties of the TextElement
class that have attached property usage. They inherit their values. Once you set a value on a visual tree item, all its children will get the same value. Unless they override it either by an explicit property assignment, or by style and so on.
Once again, text color font size and font family are governed by the value of TextElement.Foreground
, TextElement.FontSize
and TextElement.FontFamily
attached dependency properties on a specific visual element.
Some controls, like Label
explicitly set their Foreground
to some brush. It happens so that the brush is one of the SystemColors
. But it doesn't have to be true for all controls. Others (TextBlock
, TextBox
, etc.) don't override the property value and just use some default settings evaluated on startup. The same happens to FontSize
and FontFamily
. You do not need to set them wherever in order for them to work. That's how WPF works.
Supposedly, the values depend on the system theme. I believe they are evaluated during the app startup. Perhaps they are configurable.
UPDATE 2
Answers to your new questions:
How does a TextBlock get its default color, if the client app doesn't provide any style, either programmatically or through xaml?
It takes it from the inherited value of the TextElement.Foreground
attached dependency property. By default it is inherited from the root visual element, which in turn is simply set to the default value of the dependency property (Brushes.Black
). See also
How does a Label get its default color?
It takes it from the value of the TextElement.Foreground
attached dependency property. Since its default style sets it to the {DynamicResource {x:Static SystemColors.ControlTextBrushKey}
, it gets bound to the system color.
How does a TextBlock get its default font size and font family, if the client app doesn't provide any style, either programmatically or through xaml?
The same as for its text color. MSDN says that for the default value of the font size is SystemFonts.MessageFontSize which depends on system settings. Font family is determined in similar way from SystemFonts.MessageFontFamily.
Both these default values are passed to the FrameworkPropertyMetadata
constructor upon dependency property registration in the TextElement
static constructor.
Going deeper: SystemFonts.MessageFontFamily
and SystemFonts.MessageFontSize
wrap internal SystemParameters.NonClientMetrics
which in turn are retrieved from the WIN32 native SystemParametersInfo
http://msdn.microsoft.com/en-us/library/ms724947. Thus the WPF is tightly integrated with all Windows UI stuff like themes, fonts, etc.
How does a Label get its default font size and font family?
The same as for TextBlock
. Label
derives from ContentControl
which in turn derives from Control
. Control
class adds itself as an owner of the TextElement.FontFamily
and TextElement.FontSize
properties with the same default values.
See also:
UPDATE 3
You should understand the main idea: the values are inherited. It means they might be inherited from anywhere, from any control. You can tell exactly which one it is inherited from only for a certain logical tree structure. You change it a bit - and the colors change. Someone sets a property's value explicitly - and all children will inherit the value. Therefore your questions make little practival sense. But they are still interesting from the perspective of undestanding the WPF.
Overriding default values
Although you cannot change the values of the SystemFonts
properties (they are read-only), you don't have to. To change the font size and family for the whole window, simply assign the desired values to the TextElement
attached properties on the Window
:
<Window TextElement.FontSize="20" TextElement.FontFamily="Century Gothic">
..
</Window>
and all controls that do not explicitly override the inheritance will receive the settings. For those that do override - you'll have to override their default styles or even throw them away if they hard-code the values.
The same approach works for TextElement.Foreground
(and Background
and so on).
Solution 2
The default colors are pulled from the operating system's settings.
You can overwrite them by creating a brush which has the a key that references a SystemColors brush key
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Red"/>
Solution 3
According to this: http://msdn.microsoft.com/en-us/library/ms788718.aspx
By default, WPF uses the GlobalUserInterface.composite font in your Windows\Fonts directory.
And according to this: http://msdn.microsoft.com/en-us/library/system.windows.controls.textblock.fontsize(v=vs.95).aspx
A non-negative value that specifies the font size, measured in pixels. The default is 11.
In addition, you can find many of the other default values stored in various places in the MSDN site: http://msdn.microsoft.com/en-us/library/system.windows.controls.textblock.fontstyle(v=VS.95).aspx for the style, which says:
The requested font style, which is a FontStyle that is obtained from one of the FontStyles property values. The default is Normal.
mobileTofu
Updated on July 09, 2022Comments
-
mobileTofu almost 2 years
Edit: I guess the question wasn't stated very clearly. It actually composes of 4 separate ones:
- How does a
TextBlock
get its default color, if the client app doesn't provide any style, either programmatically or through xaml? - How does a
Label
get its default color? - How does a
TextBlock
get its default font size and font family, if the client app doesn't provide any style, either programmatically or through xaml? - How does a
Label
get its default font size and font family?
BTW, the questions are not about how to change or define styles for the color/font size/font family of a
TextBlock
or aLabel
, although they are somehow related. I think I already knew the answer for #2, that is aLabel
gets its color from SystemColors.ControlTextBrushKey and by overridingConrolTextBrushKey
like so:<SolidColorBrush x:Key="{x:Static SystemColors.ControlTextBrushKey}" Color="Red"/>
You would be able to "globally" change color for
Label
s. After some research, I guess I also find the answer for #1: ATextBlock
inherits the its foreground color from its containingWindow
, which by default gets itsForeground
color from SystemColors.WindowTextBrushKey. By defining a color for the WindowTextBrush like so:<Window.Resources> <SolidColorBrush x:Key="{x:Static SystemColors.WindowTextBrushKey}" Color="Yellow"/> </Window.Resources>
You would be able to change the "foreground" color for the
TextBlock
s inside theWindow
.Question #3 and #4 remain puzzles for me, but I am assuming they have to do with the SystemFonts.
Hope this makes sense. I really like to know the answers as they have been bothering me for a while. Many thanks!
Below is the original post:
If you look into the style for a
Label
in the theme (for example "aero.normalcolor.xaml") that comes with Windows, you can find<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
Which sets the color for a
Label
. But there is no where theFontSize
property is specified in the style, which I assume has something to do with the SystemFonts. For aTextBlock
, it looks even more mysterious as the style for it in "aero.normalcolor.xaml" has only 4 lines:<Style x:Key="{x:Type TextBlock}" TargetType="{x:Type TextBlock}"> <Setter Property="TextWrapping" Value="NoWrap"/> <Setter Property="TextTrimming" Value="None"/> </Style>
Where does a
Label
or aTextBlock
get the values for its color and font size/family from, if the app doesn't set any, and where are those hooks in WPF?Edit:
This is a test drive attempting to set the
TextBlock
color throughSystemColors.ControlTextBrush
(assuming that's where aTextBlock
gets its default color from, which seems to be false):<Window x:Class="TestFontColor.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <StackPanel> <StackPanel.Resources> <SolidColorBrush x:Key="{x:Static SystemColors.ControlTextBrushKey}" Color="Red"/> </StackPanel.Resources> <Button Content="This is red."/> <Label Content="This is blue."> <Label.Resources> <SolidColorBrush x:Key="{x:Static SystemColors.ControlTextBrushKey}" Color="Blue"/> </Label.Resources> </Label> <TextBlock Text="TextBlock: This is still black."/> </StackPanel>
- How does a
-
mobileTofu over 12 yearsSystemsColors doesn't seem to affect TextBlocks, though.
-
Pavel Gatilov over 12 years@mobileTofu You must be doing it wrong. Rachel is right, if you put her sample brush to a
ResourceDictionary
it will override system settings. Try usingControlTextBrushKey
instead ofHighlightBrushKey
to increase the effect. Also, try putting the brush to a higher-level logical tree item than the controls you want it to affect. Resources of aLabel
won't affect theLabel
, only its children. -
mobileTofu over 12 years@Pavel Gatilov inline style resources for a Label do affect Label. Please see my edit above. Thanks.
-
mobileTofu over 12 yearsPlease read the question before posting an answer. I don't believe either answer has provided any new information than that's already there in the original question. Many thanks.
-
mobileTofu over 12 yearsHope my comment didn't come through as rude; if that's the case, I am sorry.
-
Pavel Gatilov over 12 years@mobileTofu At this time I don't understand what your question is. Do you want to know why Labels behave differently from TextBlocks? Do you want to know how default colors and other settings are determined? Why aren't you satisfied with my or Rachel's answers?
-
Pavel Gatilov over 12 years@mobileTofu Please, see my UPDATE 2 for answers to your rephrased questions.
-
mobileTofu over 12 yearsSorry about the confusion. I guess I didn't state my questions clearly, which I updated (again), along with the attempt to answer them by myself. You said "You don't need to set those them wherever in order for them to work" and "supposedly depend on the system theme", I guess that's exactly where my puzzle is. I'd like to find out how the system or the WPF framework defines those default values, not about how the client app goes about providing its own to style a TextBlock or a Label control; although the two questions are somehow related. Hope this makes sense. Thanks!
-
mobileTofu over 12 yearsThanks for the update #3. I guess my questions could also be rephrased as to what sits on top of the inheritance trees for those properties (foreground/font size/family).
-
Pavel Gatilov over 12 years@mobileTofu Please, refer to my answers to your questions #3, 4 given in UPDATE 2. This answers them. I've also added more details on how the default settings of the WPF properties map to the WIN32 API functions ('Going deeper'). Check out if it is what you want.
-
mobileTofu over 12 yearsThanks for the update. Looks like what I'm looking for. So how do I go about defining/changing MessageFontFamily and MessageFontSize so that I see a TextBlock or Label gets inherited, either through xaml, Windows GUI or programmatically?
-
user1040323 over 5 yearsOnly TextElement.FontSize="xx" works. .FontFamily and .Foreground do not work. e.g. <Window TextElement.FontSize="16" TextElement.FontFamily="Comic Sans" TextElement.Foreground="Red"> ... </Window>