Override or add some style properties in WPF - wpf

I am porting a Bootstrap theme to WPF and faced a problem: I can't change some properties using additional style for StackPanel. I have ResourceDictionary containing BtnBase base style and BtnPrimary, BtnSecondary etc. All of them were inherited from BtnBase and contain only color properties. BtnBase does not contain any margin rule. When I try to add margin rule for a current StackPanel, there is no effect. I read about styles and knew that more than one style can't be applied, styles in ResourceDictionary have higher priority and I should use BasedOn. But I need to copy and paste my style in the StackPanel and replace BasedOn for each button variant. Is there a way to bypass it and add margin property for all styles?
code:
<StackPanel Orientation="Horizontal" Height="32">
<StackPanel.Resources>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource BtnBase}>
<Setter Property="Margin" Value="0,0,10,0"/>
</Style>
</StackPanel.Resources>
<Button Style="{DynamicResource BtnPrimary}" Content="Primary" />
<Button Style="{DynamicResource BtnSecondary}" Content="Secondary" />
<Button Style="{DynamicResource BtnSuccess}" Content="Success" />
<Button Style="{DynamicResource BtnInfo}" Content="Info" />
<Button Style="{DynamicResource BtnWarning}" Content="Warning" />
<Button Style="{DynamicResource BtnDanger}" Content="Danger" />
<Button Style="{DynamicResource BtnLight}" Content="Light" />
<Button Style="{DynamicResource BtnDark}" Content="Dark" />
</StackPanel>

You can treat all buttons as Items in ListBox.
ListBox will create a ListBoxItem for each Button, and you can add Margin to those ListBoxItems, using ItemContainerStyle. That doesn't modify Buttons styles, but creates same effect.
In ItemContainerStyle I also change ListBoxItem template to undo hover, selection colors, etc, which can change appearance - just plain ContentPresenter is left.
ItemsPanel by default is vertical StackPanel, but I changed ItemsPanel and layout to horizontal StackPanel.
<ListBox>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" Height="32"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Margin" Value="4"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<ContentPresenter/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
<Button Style="{DynamicResource BtnPrimary}" Content="Primary" />
<Button Style="{DynamicResource BtnSecondary}" Content="Secondary" />
<Button Style="{DynamicResource BtnSuccess}" Content="Success" />
<Button Style="{DynamicResource BtnInfo}" Content="Info" />
<Button Style="{DynamicResource BtnWarning}" Content="Warning" />
<Button Style="{DynamicResource BtnDanger}" Content="Danger" />
<Button Style="{DynamicResource BtnLight}" Content="Light" />
<Button Style="{DynamicResource BtnDark}" Content="Dark" />
</ListBox>

Related

WPF Button style won't apply to second button

I have two buttons that use a static common style:
<Button x:Name="BtnCreate" Height="22" Width="150" Style="{StaticResource Style.Button.Trash}"/>
<Button x:Name="aefae" Height="22" Width="150" Style="{StaticResource Style.Button.Trash}"/>
The style is very basic:
<Style TargetType="Button" x:Key="Style.Button.Trash"
BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="Content">
<Setter.Value>
<StackPanel Orientation="Horizontal" >
<Image Source="{StaticResource Image.Trash}" Width="22" Height="22"/>
<Label Content="Save" VerticalAlignment="Center" Height="26" />
</StackPanel>
</Setter.Value>
</Setter>
</Style>
The style applies to the first button and display both the image an the text however the second button does not display anything except a grey button.
Why does the second button not use the static style?
As you're trying to add the same Content to two Buttons, elements (present in Style) cannot be added to two different Logical Parents. To avoid this, you can set x:Shared="False" to your style.

Button foreground doesn't change when content is StackPanel

I have a button style defined where the template has a ContentPresenter with a name of "contentPresenter". It then has a trigger set up like this:
<ControlTemplate.Triggers>
<Trigger Property="UIElement.IsEnabled" Value="False">
<Setter Property="TextElement.Foreground" TargetName="contentPresenter" Value="#FF838383" />
</Trigger>
</ControlTemplate.Triggers>
This trigger simply changes the foreground color of a button to gray when the button is disabled. However, I have one button in my application which does not have simple text as its content. The button looks like this:
<Button Grid.Column="3" Grid.Row="3" Grid.ColumnSpan="2"
Margin="120 20 30 10"
Command="{Binding SomeCommand}">
<StackPanel Orientation="Horizontal">
<Image Source="{Binding MyImage}" Margin="0 0 2 0"
Visibility="{Binding ShowMyImage, Converter={StaticResource BooleanToVisibilityConverter}}"/>
<TextBlock Text="{Binding ButtonText}" />
</StackPanel>
</Button>
The foreground of this button is always the same whether the button is disabled or not. I'm thinking it's because the text for the button is in a textblock within the stackpanel in the content presenter, but I don't know how to get the foreground color changes to be applied to the inner textblock.
I tried changing the Property in the trigger to use "TextBlock.Foreground" instead of "TextElement.Foreground". I also tried binding the Foreground of the inner textblock to the foreground color of the closest ancestor of type FrameworkElement like this:
<TextBlock Text="{Binding ButtonText}" Foreground="{Binding RelativeSource={RelativeSource AncestorType={x:Type FrameworkElement}}, Path=(FrameworkElement.Foreground)}" />
None of this worked. What do I need to do to get the foreground color to apply to the TextBlock inside the StackPanel?
Your trigger should be in the Style, and should be setting Foreground on the Button itself, rather than on the ContentPresenter. Then it'll Just Work, with a custom template or with the default template. No need for any extra bindings.
<Style TargetType="Button" x:Key="MyButtonStyle">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="Beige" BorderBrush="Black" BorderThickness="1" Padding="6,2">
<ContentPresenter
/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="#FF838383" />
</Trigger>
</Style.Triggers>
</Style>
Usage:
<Button
IsEnabled="False"
Style="{StaticResource MyButtonStyle}"
>
<StackPanel>
<TextBlock
>Blah Blah</TextBlock>
<Button>X</Button>
</StackPanel>
</Button>
<Button Style="{StaticResource MyButtonStyle}" IsEnabled="False">Testing</Button>
Screenshot (never mind my ugly template):

I want to be able to specify a style for a tooltip on some MenuItems, how do I do that?

I want to specify a template for the tooltips of some MenuItem controls on my views. I've put the following into a resource dictionary:
<Style TargetType="{x:Type ToolTip}" x:Key="MenuItemToolTip">
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToolTip">
<HeaderedContentControl>
<HeaderedContentControl.Header>
<TextBlock FontSize="20" Background="#2288C6" Foreground="White" Padding="3">Click to report a bug</TextBlock>
</HeaderedContentControl.Header>
<HeaderedContentControl.Content>
<StackPanel>
<TextBlock Margin="0,5">Please do <Run FontWeight="Bold">not</Run> change the send To email address.</TextBlock>
<TextBlock>Also, leave the <Run FontStyle="Italic">BUG: BOTS</Run> in the subject line alone.</TextBlock>
<!-- more text blocks, but removed for brevity -->
</StackPanel>
</HeaderedContentControl.Content>
</HeaderedContentControl>
</ControlTemplate>
</Setter.Value>
</Setter>
Then in one of the views I've tried using it like so:
<MenuItem Background="{x:Null}" Foreground="#FF706C6C" Command="{Binding ViewBugReportingCommand}">
<MenuItem.Style>
<Style Resources="{StaticResource MenuItemToolTip}" />
</MenuItem.Style>
<MenuItem.Header>
<Path Data="{StaticResource BugIconData}"
Stretch="Uniform"
Fill="#77000000"
Width="20"
RenderTransformOrigin="0.25,0.25"
Height="20" />
</MenuItem.Header>
At first I tried this, but this was just as bad:
<MenuItem Background="{x:Null}" Foreground="#FF706C6C" Command="{Binding ViewBugReportingCommand}" ToolTip="{StaticResource MenuItemToolTip}">
<MenuItem.Header>
<Path Data="{StaticResource BugIconData}"
Stretch="Uniform"
Fill="#77000000"
Width="20"
RenderTransformOrigin="0.25,0.25"
Height="20" />
</MenuItem.Header>
So, how do I get my style into a resource dictionary so that I can use it on some MenuItems, but not all?
The problem with your first approach is that Style.Resources accepts a ResourceDictionary but you are setting it to a Style
Your second approach does not work because you are applying a Style object to the ToolTip property. So an implicit ToolTip is created which tries to Render your style. But since Style is not a UIElement,
what you get is a TextBlock with it's Text property set to whatever text is returned from Style.ToString, which is the name of the Style class by default.
The simplest way here would be to explicitly create a ToolTip for each of your MenuItems and set the styles there. For example:
<MenuItem Background="{x:Null}" Foreground="#FF706C6C" Command="{Binding ViewBugReportingCommand}">
<MenuItem.ToolTip>
<ToolTip Style={StaticResource MenuItemToolTip} Content="Your Tooltip text" />
</MenuItem.ToolTip>
</MenuItem>
Another option would be to add an implicit style to the Resources property of the MenuItem so that it will be applied
to all ToolTips inside the visual tree of the MenuItem.
<MenuItem ToolTip="Hello">
<MenuItem.Resources>
<Style TargetType="{x:Type ToolTip}">
.. setters
</Style>
</MenuItem.Resources>
</MenuItem>
I prefer the former because it's the simplest.
You can specify the tooltip style directly by using the tooltip control like this:
<MenuItem Background="{x:Null}"
Foreground="#FF706C6C"
Command="{Binding ViewBugReportingCommand}">
<MenuItem.ToolTip>
<ToolTip Style="{StaticResource MenuItemToolTip}" />
</MenuItem.ToolTip>
...
</MenuItem>

Monospace Margin between elements in WPF

I want the space between the child elements in, for example, StackPanel be the same. When using the same Margin for child elements, gap between neighbors doubles. I'm using a little trick to solve this, but it seems to me there is more elegant solution. May be you have one?
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="MyButtonStyle" TargetType="Button">
<Setter Property="Margin" Value="4,4,0,4" />
...
</Style>
<Style x:Key="LastMyButtonStyle" TargetType="Button" BasedOn="{StaticResource MyButton}">
<Setter Property="Margin" Value="4" />
</Style>
I'm using MyButtonStyle for all buttons except the last one, which use LastMyButtonStyle.
Put the StackPanel in another container, i.e. a Border, and set its Margin to the same value as those of the Buttons:
<Border>
<StackPanel Orientation="Horizontal" Margin="2">
<Button Margin="2" Content="Button 1"/>
<Button Margin="2" Content="Button 2"/>
<Button Margin="2" Content="Button 3"/>
</StackPanel>
</Border>

tooltip font in wpf

Does anybody know how to change the font of tooltip for ui elements?
This gives you really big tooltips in all places:
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Page.Resources>
<Style x:Key="{x:Type ToolTip}" TargetType="{x:Type ToolTip}">
<Setter Property="FontSize" Value="24"/>
</Style>
</Page.Resources>
<Grid>
<Button Content="Hey" ToolTipService.ToolTip="Hey"/>
</Grid>
</Page>
If you want to change particular tooltip you can define style closer to that tooltip, or place fontsize directly in the tooltip:
<Button Content="Hey">
<ToolTipService.ToolTip>
<TextBlock FontSize="64" Text="Hey"/>
</ToolTipService.ToolTip>
</Button>
You can do it by adding textblock as tooltip's child element
<TextBox>
<TextBox.ToolTip>
<ToolTip>
<TextBlock FontFamily="Tahoma" FontSize="10" FontWeight="Bold" Text="My tooltip text"/>
</ToolTip>
<TextBox.ToolTip>
</TextBox>
Use the FontFamily property on ToolTip

Resources