WPF - Change Scrollbar's margin of a TextBox using Styles - c#

I have a defined an implicit style for Scrollbar and set some properties and I use it for most ScrollViewrs. Part of the Style is :
<Style x:Key="{x:Type ScrollBar}" TargetType="{x:Type ScrollBar}">
<Setter Property="Background" Value="#FF283542" />
<Setter Property="Margin" Value="0,-32,0,0" />
<Setter Property="Width" Value="5" />
</Style>
But I have some TextBoxes which I want them to have the same implicit Scrollbar style for their Scrollbars but with a diffrent margin.
I can do it by adding Resources to every TextBox and override the implicit ScrollBar style like :
<TextBox Style="{StaticResource big-text-style}">
<TextBox.Resources>
<Style TargetType="{x:Type ScrollBar}"
BasedOn="{StaticResource {x:Type ScrollBar}}">
<Setter Property="Margin" Value="0"/>
</Style>
</TextBox.Resources>
</TextBox>
This code gives me the functionality I want. But the problem with this approach is that I have to write these lines of code of every TextBox! It would be much better if I could put this as part of the TextBox style itself.
I wonder is there a way to put it in the TextBox's Style so that every TextBox which has big-text-style(for example), have the overriden ScrollBar ?
Or is there a better way to implement this kind of thing ?
Thank you for the help!

You can add the overriding ScrollBar style to the Resources of the TextBox style itself:
<Style x:Key="big-text-style" TargetType="TextBox">
<Style.Resources>
<Style TargetType="{x:Type ScrollBar}" BasedOn="{StaticResource {x:Type ScrollBar}}">
<Setter Property="Margin" Value="0"/>
</Style>
</Style.Resources>
</Style>

Related

Change Font Size of all UI Elements in using Static Resource from App.xaml in WPF

I'm need to change the font size of all text across the application.
I have tried doing as follows, but that doesn't work:-
<Style x:Key="fontsize" TargetType="{x:Type FrameworkElement}">
<Setter Property="Control.FontSize" Value="20"/>
</Style>
<Style TargetType="{x:Type FrameworkElement}" BasedOn="{StaticResource fontsize}"/>
When I try setting as follows then that works fine but doesn't get applied to all elements & needs to apply that for all different types of elements aperately.
<Style TargetType="TextBlock" BasedOn="{StaticResource fontsize}"/>
<Style TargetType="TextBox" BasedOn="{StaticResource fontsize}"/>
<Style TargetType="DataGridCell" BasedOn="{StaticResource fontsize}"/>
<Style TargetType="MenuItem" BasedOn="{StaticResource fontsize}"/>
<Style TargetType="DatePicker" BasedOn="{StaticResource fontsize}"/>
Also I would like to ask that, is there a way that I can override the Global Style for a particular element, like Heading text should be of different size on a user control?
in App.xaml
<Style TargetType="TextBlock">
<Setter Property="FontSize" Value="20"/>
<Setter Property="FontWeight" Value="Bold"/>
</Style>
Create a global style for the window in App.xaml.
<Application.Resources>
<Style x:Key="WindowStyle" TargetType="{x:Type Window}">
<Setter Property="FontStyle" Value="Italic" />
<Setter Property="FontSize" Value="24" />
<Setter Property="Foreground" Value="Green"/>
</Style>
</Application.Resources>
and set that style for the required windows.
<Window x:Class="YourNamespace.MainWindow" Style="{StaticResource WindowStyle}".....>
for overriding the style for a usercontrol
<local:UserControl1>
<local:UserControl1.Style>
<Style TargetType="UserControl">
<Setter Property="FontSize" Value="10"/>
</Style>
</local:UserControl1.Style>
</local:UserControl1>
There are two controls this involves.
You're maybe thinking "hey what about this cell or that calendar".
Their templates show text in a textblock.
When you set Header on a menuitem or content on a label, you get a textblock generated.
You therefore "only" need to set style on both textblock and textbox:
<Application.Resources>
<ResourceDictionary>
<Style TargetType="TextBlock">
<Setter Property="FontSize" Value="20"/>
</Style>
<Style TargetType="TextBox">
<Setter Property="FontSize" Value="20"/>
</Style>
</ResourceDictionary>
</Application.Resources>
</Application>
Having said that.
As Clemens pointed out.
The Font size and styling dependency properties are marked as inherits, so if you just have mainwindow then you could just set on that.
It's not just "obvious" that a label ends up with a textblock in it when you set content though. Similarly a menuitem and header. Hence I thought it worth posting this answer.

Is it possible to set FontSize for all controls at once? [duplicate]

This question already has answers here:
WPF global font size
(11 answers)
Closed 4 years ago.
I need to set FontSize property for all controls in my wpf-layout at once.
I mean I don't want to set it for labels, then for chechboxes etc. I want to set it for all controls which support this property.
So, in "Settings" of my module I have values of font size for buttons and for the rest of controls. For buttons I set font size this way:
<Style TargetType="Button">
<Setter Property="FontSize" Value="{Binding Source={x:Static properties:Settings.Default}, Path=ButtonFontSize}" />
</Style>
Now I need to set FontSize for the rest of controls.
You can set it on the window i guess, as it should be inherited from the Parent Control.
<Style TargetType="{x:Type Window}">
<Setter Property="FontSize" Value="24" />
</Style>
Copied from this answer.
I'd do it this way:
<Window.Resources>
<Style TargetType="{x:Type Control}" x:Key="baseStyle">
<Setter Property="FontSize" Value="100" />
</Style>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource baseStyle}"></Style>
<Style TargetType="{x:Type Label}" BasedOn="{StaticResource baseStyle}"></Style>
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource baseStyle}"></Style>
<Style TargetType="{x:Type ListView}" BasedOn="{StaticResource baseStyle}"></Style>
<!-- ComboBox, RadioButton, CheckBox, etc... -->
</Window.Resources>
If you want to set the fontsize for all controls of one specific tipe you could use this
<Window.Resources>
<Style TargetType="{x:Type TextBox}">
<Setter Property="FontSize" Value="24" />
</Style>
<Style TargetType="{x:Type Textblock}">
<Setter Property="FontSize" Value="20" />
</Style>
</Window.Resources>
If you have many styles and want to keep the variable editable it makes sense to define it above like so:
<Window.Resources>
<System:Double x:Key="stdFontSize">15</System:Double>
<Style TargetType="{x:Type TextBox}">
<Setter Property="FontSize" Value="stdFontSize" />
</Style>
<Style TargetType="{x:Type Textblock}">
<Setter Property="FontSize" Value="stdFontSize" />
</Style>
</Window.Resources>

How can I stop ToolTips from inheriting my TextBlock style?

I've defined a style within my application resources that I want all of my textblocks to inerit :
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Effect">
<Setter.Value>
<DropShadowEffect BlurRadius="1" ShadowDepth="0" />
</Setter.Value>
</Setter>
<Setter Property="Foreground" Value="White" />
<Setter Property="FontFamily" Value="Arial" />
<Setter Property="FontWeight" Value="Bold" />
</Style>
I don't want to have to go through and explicitly dictate the style on each textblock - I just want all of them to inherit this style naturally.
Unfortunately, when I define a tooltip, that tooltip also picks up this style. I'm guessing it's because the thing incorporates a TextBlock somewhere in it's design.
What I AM okay with is having to go through and style each defined tooltip ( since they are used less ubiquitously throughout my application ), so if there's some way to define a tooltip style that will override the inherited textblock style, I'm fine with that.
So, what can I do to stop my tooltips from inheriting the TextBlock style?
It's a terrible idea to set a global implicit style on TextBlock, and this is why. TextBlock is the primitive that displays text. It's much better to set the implicit TextBlock style only where it's needed, not universally.
Or consider using Label instead of TextBlock for the styled text instances, and have an implicit Label style. That's one reason why Label exists. You can style the padding/margin etc. to make it look exactly the way you want.
But if you want the quick and dirty and easy way to work around a bad decision, you can use the implicit-style-localized-within-a-style trick that grandpa used to flummox General Rommel at El Alamein:
<Style TargetType="ToolTip">
<Style.Resources>
<!-- Implicit style for TextBlocks within ToolTips -->
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="Black" />
<Setter Property="FontWeight" Value="Regular" />
<Setter Property="Effect" Value="{x:Null}" />
</Style>
</Style.Resources>
<Setter Property="Foreground" Value="Black" />
<Setter Property="FontWeight" Value="Regular" />
<Setter Property="Effect" Value="{x:Null}" />
</Style>

Watermark fontsize/family

I am currently creating a TextBox with a watermark text and have a little styling problem.
To create the Watermark itself I have included the code explained in here
Watermark / hint text / placeholder TextBox in WPF
I did not use the accepted answer, but the one with the highest votes. (the one using Adorner)
My textblock looks like this:
<AdornerDecorator>
<TextBox HorizontalAlignment="Right"
VerticalAlignment="Center"
Width="190"
Padding="16,2,20,2">
<utils:WatermarkService.Watermark>
<TextBlock Text="Search" />
</utils:WatermarkService.Watermark>
</TextBox>
</AdornerDecorator>
Now I face the problem that with this attached property, the textblock in it gets out of scope from my styling I have declared in app.xaml.
The styling looks like this:
<Style TargetType="{x:Type Window}">
<Setter Property="FontFamily"
Value="Tahoma" />
<Setter Property="FontSize"
Value="8pt"></Setter>
<Setter Property="Background"
Value="{DynamicResource {x:Static SystemColors.ControlLightBrushKey}}" />
</Style>
How is it possible to style the textblock within the attached property in app.xaml, preferable with basedon this style so I dont have to declare it serval times.
Declare same style for TextBlock as well in Application resources. This way it will be applied to all TextBlocks in your application no matter whether they are part of Adorners or window.
<Style TargetType="{x:Type TextBlock}">
<Setter Property="FontFamily"
Value="Tahoma" />
<Setter Property="FontSize"
Value="8pt"></Setter>
<Setter Property="Background"
Value="{DynamicResource {x:Static SystemColors.ControlLightBrushKey}}"/>
</Style>
UPDATE
If you don't want to duplicate resources, best you can get is use Label instead of TextBlock. That way you can have style applied on Control and can derive styles for Window and Label from that.
But this won't work for TextBlock since it doesn't derive from Control.
<Style TargetType="Control" x:Key="BaseStyle">
<Setter Property="FontFamily" Value="Tahoma" />
<Setter Property="FontSize" Value="8pt"></Setter>
<Setter Property="Background"
Value="{DynamicResource {x:Static SystemColors.ControlLightBrushKey}}"/>
</Style>
<Style TargetType="{x:Type Window}"
BasedOn="{StaticResource BaseStyle}"/>
<Style TargetType="{x:Type Label}"
BasedOn="{StaticResource BaseStyle}"/>
Then if you use Label inside AdornerDecorator in place of TextBlock, it will work fine.

Can I have one Style with multiple TargetType in WPF?

As titled, and I mean something like below:
<Style TargetType="{x:Type TextBlock}"
TargetType="{x:Type Label}"
TargetType="{x:Type Button}" >
This is actually for the sake of using a 3rd party control, I have inherited their class. But the template doesn't apply to the SubClass because the TargetType is on the base class. So I would like to set multiple TargetTypes to make it able to apply for both.
No you cannot, however I often create a style for a shared base class such as FrameworkElement, and then create my individual control styles that are BasedOn the base style
<Style TargetType="{x:Type FrameworkElement}">
<!-- Shared Setters -->
</Style>
<Style TargetType="{x:Type TextBlock}" BasedOn="{StaticResource {x:Type FrameworkElement}}" />
<Style TargetType="{x:Type Label}" BasedOn="{StaticResource {x:Type FrameworkElement}}" />
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type FrameworkElement}}" />
A more flexible variation of Rachel's answer is to use resourceKey for BasedOn.
So, instead of:
<Style TargetType="{x:Type FrameworkElement}">
<!-- Shared Setters -->
</Style>
<Style TargetType="{x:Type TextBlock}" BasedOn="{StaticResource {x:Type FrameworkElement}}" />
Do something like:
<Style x:Key="commonStyle" TargetType="{x:Type FrameworkElement}">
<!-- Shared Setters -->
</Style>
<Style TargetType="{x:Type TextBlock}" BasedOn="{StaticResource commonStyle}" />
This gives more options as some styles can be based on commonStyle, and some on e.g. commonStyle2, where both commonStyle and commonStyle2 have FrameworkElement as target type.
The answer is no.
TargetType is a property of Style and can only be set once. To insure type safty, the style should target a specific type in order to know what properties to set.
However, there is a work around. You can take the common properties of all the types you have and define them in one style. Then make specific styles for each of the specific controls and use the BasedOn property to inherit from the basic style.
Based on Rachel's answer, for cleaner code, you can remove the x:Type within the Markup Extension and just use the Type:
<Style TargetType="Label">
<!-- Shared Setters -->
</Style>
Is the same as:
<Style TargetType="{x:Type Label}">
<!-- Shared Setters -->
</Style>
Actually I found out that in a grid you can only set the style of one item. However, in a stackpanel you can set the style of multiple items.
See this code:
<Grid>
<StackPanel>
<StackPanel.Resources>
<Style TargetType="TextBlock">
<Setter Property="FontSize" Value="12"></Setter>
<Setter Property="VerticalAlignment" Value="Center"></Setter>
<Setter Property="HorizontalAlignment" Value="Center"></Setter>
<Setter Property="Margin" Value="5"></Setter>
</Style>
<Style TargetType="TextBox">
<Setter Property="Width" Value="100"></Setter>
<Setter Property="Height" Value="25"></Setter>
<Setter Property="Margin" Value="5"></Setter>
</Style>
<Style TargetType="Button">
<Setter Property="Margin" Value="5"></Setter>
<Setter Property="Height" Value="30"></Setter>
<Setter Property="Width" Value="100"></Setter>
</Style>
</StackPanel.Resources>
<StackPanel Orientation="Horizontal">
<TextBlock>Kanban ID</TextBlock>
<TextBox></TextBox>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock>Customer Name</TextBlock>
<TextBox></TextBox>
</StackPanel>
<Button>Save</Button>
</StackPanel>
</Grid>
If you were to remove the place it below the and change to you will see that the objects aren't set, only the last object's properties is changed.
Hope this helps.

Categories

Resources