Using Margin in TabControl.ItemContainerStyle clips Headers - wpf

Want to add some margin for initial TabControl headers:
use this ItemContainerStyle
<TabControl mahapps:TabControlHelper.Underlined="SelectedTabItem">
<TabControl.ItemContainerStyle>
<Style TargetType="TabItem" BasedOn="{StaticResource {x:Type TabItem}}">
<Setter Property="Margin" Value="0,0,40,0"/>
</Style>
</TabControl.ItemContainerStyle>
</TabControl>
result:
Padding
Using Padding instead of Margin is not an option due to Underline
How to save all letters? Letters are good fellows.
(Update) Negative Margin
Tried <Setter Property="Margin" Value="-10,0,0,0"/>

Related

How to style last (or first) child of StackPanel differently than the rest?

I'm applying styles to StackPanel:
<Style TargetType="{x:Type StackPanel}">
<Style.Resources>
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource TextboxStyle}">
<Setter Property="Margin" Value="0,0,0,5"/>
</Style>
</Style.Resources>
</Style>
Basically, it adds margin on bottom of every TextBox in StackPanel. What is bad, that last child will have unnecessary margin. So I need to reset it to zero, but only for that last element. WPF is certainly not a CSS, which have :last-child selector and it's probably more quirky to do that.

MahApps setting style based on existing style has strange output

I copyied MahApps DataGrid's source code and It works fine if I change directly on the style such as setting HorizontalAlignment from left to right. But if I did
<Style BasedOn="{StaticResource MetroDataGridColumnHeader}" TargetType="{x:Type DataGridColumnHeader}"
x:Key="MetroDataGridColumnHeader1">
<Setter Property="HorizontalAlignment" Value="Right"></Setter>
</Style>
and replace the MetroDataGridColumnHeader with the new MetroDataGridColumnHeader1 inside DataGrid style, It gives strange output. Metro effects disappears.Any ideas?
You should set the HorizontalContentAlignment not the HorizontalAlignment.
<Style BasedOn="{StaticResource MetroDataGridColumnHeader}"
TargetType="{x:Type DataGridColumnHeader}"
x:Key="RightAlignmentMetroDataGridColumnHeader">
<Setter Property="HorizontalContentAlignment"
Value="Right" />
</Style>
Hope this helps.

WPF - Use control inheritance for standard-styled controls?

I have a WPF application with many windows and user controls, and I'd like to implement standard styles for certain controls that appear throughout the application. As an example, say I need two standard TextBlocks throughout the application: one for large headings, one for small headings. And the only difference between them is the font size, say 36 and 24 respectively. All other properties (color, fontfamily, etc.) could be set by a TextBlock template or global TargetType="{x:Type TextBlock}" styles.
Of course I could create two global named styles that just set the font size and apply those staticresource styles liberally throughout the XAML to my TextBlocks, or at the highest possible level above the TextBlocks that would not interfere with other TextBlocks. But as an alternative, which would remove the requirement for setting the Style tag in many places, is inheriting from TextBlock is a good way to go?
TextBlock controls:
class TextBlockLargeHeading : TextBlock
{
public TextBlockLargeHeading()
{ }
}
class TextBlockSmallHeading : TextBlock
{
public TextBlockSmallHeading()
{ }
}
Global resource:
<Application.Resources>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="Red" />
</Style>
<Style TargetType="MyApp:TextBlockLargeHeading" BasedOn="{StaticResource {x:Type TextBlock}}" >
<Setter Property="FontSize" Value="36" />
</Style>
<Style TargetType="MyApp:TextBlockSmallHeading" BasedOn="{StaticResource {x:Type TextBlock}}" >
<Setter Property="FontSize" Value="24" />
</Style>
</Application.Resources>
Then, to use them anywhere, simply reference the custom textblocks:
<StackPanel>
<MyApp:TextBlockLargeHeading Text="Large" />
<MyApp:TextBlockSmallHeading Text="Small" />
</StackPanel>
Which would create two Red TextBlocks with the appropriate font sizes.
Is this a reasonable approach? Are there any gotcha's if I've got 100's of instances of these, maintainability-wise or otherwise? Is there a better (safer or less code/XAML) approach? Perhaps using User Controls instead?
Thanks!
There's no reason to do all that. Create your styles and use them directly.
....
<Style x:Key="DefaultTextBlockStyle" TargetType="TextBlock">
<Setter Property="Foreground" Value="Red" />
<Setter Property="FontSize" Value="24" />
</Style>
<Style x:Key="LargeTextBlockStyle" TargetType="TextBlock" BasedOn="{StaticResource DefaultTextBlockStyle}">
<Setter Property="FontSize" Value="36" />
</Style>
<!-- Style applies to all TextBoxes -->
<Style TargetType="{x:Type TextBlock}" BasedOn="{StaticResource DefaultTextBlockStyle}" />
...
<StackPanel>
<TextBlock Text="Large" Style="{StaticResource LargeTextBlockStyle}"/>
<TextBlock Text="Small"/>
</StackPanel>

How to add padding inbetween items in a WPF ListView?

I have a horizontal ListView which I would like to ensure that there is some padding between the items (in my case I have Grid inside of the item template), but I don't want there to be any extra padding for the last grid
I want there to be padding where the red line is.
EDIT
H.B.'s suggestion was really helpful, here is the style that I added to get a 5px margin between grids...
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Margin" Value="5 0 0 0" />
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource PreviousData}}" Value="{x:Null}">
<Setter Property="Margin" Value="0" />
</DataTrigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
You can set a Padding in the ItemContainerStyle of the ListView. You can use a DataTrigger on RelativeSource PreviousData being null to make it conditional.
Alternatively you could create a new Panel which has a concept of spacing.

Can you define multiple TargetTypes for one XAML style?

In HTML/CSS you can define a style which can be applied to many types of elements, e.g.:
.highlight {
color:red;
}
can be applied to both P and DIV, e.g.:
<p class="highlight">this will be highlighted</p>
<div class="highlight">this will also be highlighted</div>
but in XAML you seem to have to define the TargetType for styles, otherwise you get an error:
<Style x:Key="formRowLabel" TargetType="TextBlock">
is there a way to allow a XAML style to be applied to multiple elements or even to leave it open as in CSS?
The setters in WPF styles are checked during compile time; CSS styles are applied dynamically.
You have to specify a type so that WPF can resolve the properties in the setters to the dependency properties of that type.
You can set the target type to base classes that contain the properties you want and then apply that style to derived classes. For example, you could create a style for Control objects and then apply it to multiple types of controls (Button, TextBox, CheckBox, etc)
<Style x:Key="Highlight" TargetType="{x:Type Control}">
<Setter Property="Foreground" Value="Red"/>
</Style>
...
<Button Style="{StaticResource Highlight}" Content="Test"/>
<TextBox Style="{StaticResource Highlight}" Text="Test"/>
<CheckBox Style="{StaticResource Highlight}" Content="Test"/>
<!-- Header text style -->
<Style x:Key="headerTextStyle">
<Setter Property="Label.VerticalAlignment" Value="Center"></Setter>
<Setter Property="Label.FontFamily" Value="Trebuchet MS"></Setter>
<Setter Property="Label.FontWeight" Value="Bold"></Setter>
<Setter Property="Label.FontSize" Value="18"></Setter>
<Setter Property="Label.Foreground" Value="#0066cc"></Setter>
</Style>
<!-- Label style -->
<Style x:Key="labelStyle" TargetType="{x:Type Label}">
<Setter Property="VerticalAlignment" Value="Top" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="Margin" Value="0,0,0,5" />
</Style>
I think both of these methods of declaring a style might answer your question.
In the first one, there is no TargetType specified, but the property names are prefixed with 'Label'. In the second one, the style is created for Label objects.
Another method to do it is:
<UserControl.Resources>
<Style x:Key="commonStyle" TargetType="Control">
<Setter Property="FontSize" Value="24"/>
</Style>
<Style BasedOn="{StaticResource commonStyle}" TargetType="ListBox"/>
<Style BasedOn="{StaticResource commonStyle}" TargetType="ComboBox"/>
</UserControl.Resources>
I wanted to apply a style to a Textblock and a TextBox but the selected answer didn't work for me because Textblock doesn't inherit from Control, in my case I wanted to affect the Visibility property, so I used FrameworkElement
<Style x:Key="ShowIfRequiredStyle" TargetType="{x:Type FrameworkElement}">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ShowIfRequiredStyle, UpdateSourceTrigger=PropertyChanged}" Value="true">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
<TextBlock Style="{StaticResource ResourceKey=ShowIfRequiredStyle}"/>
<TextBox Style="{StaticResource ResourceKey=ShowIfRequiredStyle}"/>
This works for the Visibility property because both items inherit from Frameworkelement and the property is defined there. Of course this will not work for properties defined only in Control, you can search the hierarchy tree and try to find a base class, anyway I thought this could help someone since this is a top search result and the selected answer is a little incomplete.
There is an alternative answer to the question. You CAN leave the TargetType parameter off the style altogether which will allow it to apply to various different controls, but only if you prefix the property name with "Control."
<Style x:Key="Highlight">
<Setter Property="Control.Foreground" Value="Red"/>
</Style>
Obviously, this only works for properties of the base control class. If you tried to set ItemsSource say, it would fail because there is no Control.ItemsSource
I got this working
<Style x:Key="HeaderStyleThin" TargetType="{x:Type Border}">
<Setter Property="Background" Value="Black" />
<Style.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Background=" Value="Red" />
</Style>
</Style.Resources>
</Style>

Resources