TextBox border radius style in WPF - c#

I checked similar questions but I couldn't figure out the underlying logic.
I am trying to add CornerRadius to a TextBox in a WPF project.
Here's what I tried so far:
In App.xaml I created a Style that I intend to reuse:
<Style x:Key="TextBoxStyle" TargetType="{x:Type TextBox}">
<Setter Property="Height" Value="27"/>
<Setter Property="Padding" Value="5.5"/>
<Setter Property="BorderThickness" Value="0"/>
</Style>
Adding: <Setter Property="Border.CornerRadius" Value="5"/> didn't work. However, the following worked, but with side effects (all borders where rounded):
<Style TargetType="{x:Type Border}">
<Setter Property="CornerRadius" Value="5"/>
</Style>
I want to keep the styles separate and basically use them like this:
<TextBox x:Name="ExampleTb" Style="{StaticResource TextBoxStyle}"/>
Can you please help me/ point me in the right direction?

It is actually very simple to achieve this, just follow these steps:
Step 1. Add a textbox to your window, right click on your textbox and select "Edit Template \ Edit a Copy..."
This will take you to the control template designer.
Step 2. Check this picture:
https://postimg.org/image/9h5ng8p9t/
P.S. I find blend better suited to design controls.

Related

C# WPF How do I add a border to a style?

I'm creating a style for buttons in App.xaml. How can I add a border to the style? And how can I then use the style in MainWindow.xaml?
I couldn't find how to do it. I don't want to put it in a separate style for the sake of border.
in App.xaml
<Style x:Key="BorderedButton" TargetType="Button">
<Setter Property="BorderBrush" Value="HotPink"/>
<Setter Property="BorderThickness" Value="2"/>
</Style>
and in the view
<Button Style="{StaticResource BorderedButton}"/>

Override style on parts of ComboBox scrollbar

After lots of research, I stumbled across a relatively simple way to target just specific parts of the control style without using the entire control template. It's partially successful, but I need a little help getting all the way to the end.
Specifically, I am trying to override the Thumb button color of the scrollbar in the dropdown of a ComboBox. The cool technique I came across is the following, which utilizes nested Style.Resources to access the lower objects...
<Style x:Key="MyComboBoxStyle" TargetType="{x:Type ComboBox}">
<Style.Resources>
<Style TargetType="ScrollViewer">
<Style.Resources>
<Style TargetType="ScrollBar">
<Setter Property="Background" Value="LightGreen" />
<Style.Resources>
<Style TargetType="Track">
<Setter Property="Cursor" Value="Cross" />
<Style.Resources>
<Style TargetType="Thumb">
<Setter Property="Background" Value="Red"/>
<Setter Property="Cursor" Value="Hand" />
</Style>
</Style.Resources>
</Style>
<Style TargetType="RepeatButton">
<Setter Property="Background" Value="Red"/>
<Setter Property="Cursor" Value="Hand" />
</Style>
</Style.Resources>
</Style>
</Style.Resources>
</Style>
</Style.Resources>
<!--- rest of ComboBox style definition follows... -->
By sequentially drilling down into the complex control style tree, using nested Style.Resources, I am able to target specific aspects of a control style, without needing the entire style definition.
The xaml code above successfully drills all the way down to the "Track"... I can change things like the margin, cursor, etc. of the Track. But, I just can't seem to get that last step to the Thumb. Also, I can't seem to access the Repeat buttons, which should be at the same level (in the object tree) as the Track.
Looking at the style template for ScrollBars seems to show that the object tree is ScrollBar->Track->Thumb... but I seem to be missing something?
Any ideas on how to get access to the Thumb color?
The default style for the ScrollBar sets the Style property of the Thumb explicitly in the Track:
<Track x:Name="PART_Track" ...>
...
<Track.Thumb>
<Thumb Style="{StaticResource ScrollBarThumbVertical}"/>
</Track.Thumb>
</Track>
This means that your implicit Thumb style won't be applied.
So you will have to define a custom complete ControlTemplate for the ScrollBar to be able to modify the style/template of the Thumb.
Alternatively, you may consider to look it up in the visual tree at runtime and set any of its properties programmatically.

WPF Style at Windows or App level yields different results

I'm trying to learn Styling in WPF and encountered a funny thing:
There is a difference when I apply a style at application or (main) window level.
When I define the following resource in the App.xaml:
<Application.Resource>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="FontStyle" Value="Italic" />
</Style>
<Style TargetType="{x:Type GroupBox}">
<Setter Property="FontWeight" Value="Bold" />
</Style>
<Application.Resource>
the GroupBox caption is bold and italic.
When I instead define the styling in the MainWindow.xaml:
<Window.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="FontStyle" Value="Italic" />
</Style>
<Style TargetType="{x:Type GroupBox}">
<Setter Property="FontWeight" Value="Bold" />
</Style>
</Window.Resources>
The GroupBox caption box is only bold and not italic.
Can anybody explain this behavior?
In picking TextBlock you have unearthed something. TextBlock is not derived from Control, and thus behaves slightly differently.
See https://stackoverflow.com/a/27065140/4258144 :
there is a curious rule in WPF implicit styles are only inherited
across template boundaries by elements which inherit from the Control
class
I guess you can add to that, "unless it is globally specified in App.xaml".
UPDATE:
Following comments, here's a look at a GroupBox visual tree, taken from Snoop.

Change foreground color of ComboBoxItem when ComboBox is hovered

At the moment, I'm styling WPF controls. This is how my custom <Button> looks hovered.
And this is how <ComboBox> looks when mouse is over it.
Simply, I want to be able to change foreground color of currently selected ComboBoxItem when whole ComboBox is hovered. In this example, I'd like to have similiar yellow color like on <Button> control.
The problem is, that <ComboBox> has different ControlTemplates for ComboBox item and toggle button. I don't know how to interact between those two.
The template for <ComboBox> is pretty big, so I'm not going to post it here. Also, you don't have to post full answer if it's not required to explain the problem.
OK, I found a solution. You need to edit default ComboBox templates.
In Visual Studio 2013 you can get a default template in Designer by clicking right mouse button on ComboBox -> Edit template -> Edit a copy...
In <ControlTemplate x:Key="ComboBoxTemplate" TargetType="{x:Type ComboBox}"> you have to add a following trigger:
<ControlTemplate.Triggers>
...
<Trigger Property="IsMouseOver" TargetName="toggleButton" Value="true">
<Setter Property="TextElement.Foreground" TargetName="contentPresenter" Value="Yellow" />
</Trigger>
...
</ControlTemplate.Triggers>
Also, apply a style to ComboBoxItem:
<Style TargetType="{x:Type ComboBoxItem}">
<Setter Property="Foreground" Value="Black"/>
</Style>
Now, it works like a charm.

How do I know whether to use a style or override a control template?

This question is inspired by this recent question and other situations I've encountered in my WPF development. How do I know whether it is enough to set a style on a control to override some default behavior vs creating a new control template?
More concretely, in the question above, the author wants to change the look of a ListBoxItem when it is selected. (See code reprinted below). Everything works, except the Background property. How is one supposed to know that they should override the Control Template for this?
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Content" Value="{Binding Path=Name}"/>
<Setter Property="Margin" Value="2"/>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="FontSize" Value="18"/>
<Setter Property="Background" Value="Yellow"/>
<Setter Property="Foreground" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
As to whether to use a style or template Ray provided a great response.
As to how to solve your problem without creating a template, maybe I can help.
The background color is being set by the SystemColors. Using Blend and creating a template you can see the exact xaml.
So if NO TEMPLATES! is a requirement you can always change what that resource is.
Example :
<ListBox>
<ListBox.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}"
Color="Yellow" />
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Content" Value="{Binding Path=Name}"/>
<Setter Property="Margin" Value="2"/>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="FontSize" Value="18"/>
<Setter Property="Foreground" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
</ListBox.Resources>
<ListBoxItem>Test 1</ListBoxItem>
<ListBoxItem>Test 2</ListBoxItem>
<ListBoxItem>Test 3</ListBoxItem>
</ListBox>
That will give you the background color for that given ListBox and not screw up anything else in the app.
Styles can be thought of very closely to CSS styles in HTML. If all you want to do is change the basic properties of a control such as Background, Foreground or whatever properties it exposes then a Style is exactly what you need. Styles also allow you to apply triggers so for animations, a style is also sufficient.
If you're finding you want to change the intrinsice behaviours / inner workings on a control then a control template is what you want. For example, if you want to change how a button is laid out by adding some sort of grid behaviour, then using a control template is the way forward.
Unfortunately, for your specific example, you don't know unless you try it. Basically you first try it with a Style....and if that doesn't work for whatever reason, then you write a ControlTemplate. You usually only end up writing ControlTemplates for the reasons Ray mentioned.
My guess is that the trigger you're trying to set has also been hardcoded in the ControlTemplate...which is bad design imo because it prevents the Style from overriding it.
By "Background" I take it to mean the "blue" rectangle that surrounds the ListBoxItem when it is selected?
This is actually the FocusVisualStyle property, which is a style that describes what the item should look like when it is focused. The Control explicitly sets this property (described here), so in order to override it, you will have to redefine the Control Template, making sure to use a default Style setter to set it to {x:Null}.

Categories