I override default styles of some controls in code. After this i want to disable all custom styles for all children(deep recursion) of some control. For example xaml:
<StackPanel>
<StackPanel.Resources>
<Style TargetType="Button">
<Setter Property="Background" Value="Red"/>
</Style>
<Style TargetType="TextBlock">
<Setter Property="Background" Value="Red"/>
</Style>
</StackPanel.Resources>
<Button>red style here is ok</Button>
<TextBlock> also ok</TextBlock>
<StackPanel>
<StackPanel.Resources>
<!-- magic command to disable ALL custom styles, for all controls like
<Style TargetType = "FrameworkElement"/> -->
</StackPanel.Resources>
<Button> no style plz </Button>
<TextBlock> bad style-_- </TextBlock>
</StackPanel>
</StackPanel>
I know that i can use style=null, but its bad solution for me, because i need to apply this trick for every type of controls. How can i solve my problem?
You could inject a blank Style that would take precedence over your other Style. Like:
<StackPanel>
<StackPanel.Resources>
<Style TargetType="Button">
<Setter Property="Background" Value="Red"/>
</Style>
<Style TargetType="TextBlock">
<Setter Property="Background" Value="Red"/>
</Style>
</StackPanel.Resources>
<Button>red style here is ok</Button>
<TextBlock> also ok</TextBlock>
<StackPanel>
<StackPanel.Resources>
<!-- magic command to disable ALL custom styles, for all controls -->
<Style TargetType="Button" />
<Style TargetType="TextBlock" />
</StackPanel.Resources>
<Button> no style plz </Button>
<TextBlock> bad style-_- </TextBlock>
</StackPanel>
</StackPanel>
Related
I want to define a style for the text box and within the style I want to bind to a property which the corresponding style applies to. Something like this:
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="True">
<Setter Property="ToolTip">
<Setter.Value>
<TextBlock Text="{Binding ????Bind to the textbox TEXT property????}">
</TextBlock>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
Is this possible at all?
Here the full Window:
<Window x:Class="StyleBinding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:StyleBinding"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="True">
<Setter Property="ToolTip">
<Setter.Value>
<TextBlock Text="{Binding Text, RelativeSource={RelativeSource Self}}"/>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<TextBox HorizontalAlignment="Left" Height="34" Margin="235,140,0,0" TextWrapping="Wrap" IsEnabled="True"
Text="Just a simple text" VerticalAlignment="Top" Width="284">
</TextBox>
</Grid>
</Window>
You just have to use a RelativeSource binding to access the Text property of the TextBox.
<Setter Property="ToolTip" Value="{Binding Text, RelativeSource={RelativeSource Self}}"/>
In case you build a custom tool tip template in your style, you can do it like this.
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
<Setter Property="ToolTip">
<Setter.Value>
<ToolTip>
<TextBlock Text="{Binding PlacementTarget.Text, RelativeSource={RelativeSource AncestorType={x:Type ToolTip}}}"/>
</ToolTip>
</Setter.Value>
</Setter>
</Style>
The PlacementTarget of the ToolTip is the TextBox here.
Here's a working example:
<Style BasedOn="{StaticResource {x:Type TextBox}}" TargetType="{x:Type TextBox}">
<Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=Text}" />
</Style>
The key is to use a RelativeSource binding of Self.
There's no need to set a trigger on IsEnabled because a ToolTip will only display on an enabled control by default.
I'm styling hyperlinks that appear within a border with the style "FooterPanel" as follows:
<Style x:Key="FooterPanel" TargetType="{x:Type Border}">
<Style.Resources>
<Style TargetType="{x:Type Hyperlink}">
<Setter Property="Foreground" Value="{StaticResource FooterPanelLinkBrush}"/>
</Style>
</Style.Resources>
</Style>
I also now have created a style to create a button as a hyperlink (so I can get properties such as IsDefault and IsCancel on a hyperlink):
<Style x:Key="LinkButton" TargetType="{x:Type Button}">
<Setter Property="Focusable" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center">
<Hyperlink Command="{TemplateBinding Command}" CommandParameter="{TemplateBinding CommandParameter}">
<Run Text="{TemplateBinding Content}"/>
</Hyperlink>
</TextBlock>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Normal hyperlinks within FooterPanel receive the FooterPanelLinkBrush foreground, but if I use LinkButton within a FooterPanel, the style is not applied. Is there a way to get the ControlTemplate to inherit the styles within the FooterPanel instead of any global hyperlink styles?
Edit:
According to this answer https://stackoverflow.com/a/9166963/2383681 there is special handling that means the Hyperlink won't receive the styles defined in the FooterPanel as it's not derived from Control.
I'm not sure what I'm trying to do is therefore possible without some code-behind, so I think I'm just going to workaround this and create a new style for FooterPanelLinkButton and explicitly reference this for the buttons that are in a footer panel. It would be interesting to know if this is possible however without doing that.
You can create a separate Style for the HyperLink:
<Style x:Key="FooterPanelLink" TargetType="{x:Type Hyperlink}">
<Setter Property="Foreground" Value="{StaticResource FooterPanelLinkBrush}"/>
</Style>
And then use this Style in the Resources of the FooterPanel and LinkButton styles in the following way:
<Style x:Key="FooterPanel" TargetType="{x:Type Border}">
<Style.Resources>
<Style TargetType="Hyperlink" BasedOn="{StaticResource FooterPanelLink}" />
</Style.Resources>
</Style>
<Style x:Key="LinkButton" TargetType="{x:Type Button}">
<Style.Resources>
<Style TargetType="Hyperlink" BasedOn="{StaticResource FooterPanelLink}" />
</Style.Resources>
<Setter Property="Focusable" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center">
<Hyperlink Command="{TemplateBinding Command}" CommandParameter="{TemplateBinding CommandParameter}">
<Run Text="{TemplateBinding Content}"/>
</Hyperlink>
</TextBlock>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
This way the HyperLink inside the LinkButton will use the color you assigned in the FooterPanelLink style.
I'm trying to customize my ToggleButtons so that when checked they say 'Yes' in green and when not checked, say 'No' in red.
I've created the following style which is sitting in my Styles resource dictionary.
<!-- ToggleButtons -->
<Style x:Key="YesNoToggleStyle" TargetType="ToggleButton">
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Background" Value="SpringGreen" />
<Setter Property="Content">
<Setter.Value>
<TextBlock Text="Yes"/>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsChecked" Value="False">
<Setter Property="Background" Value="Crimson" />
<Setter Property="Content">
<Setter.Value>
<TextBlock Text="No"/>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
This works ... sort of. If the ToggleButton is the last one of either value, then it displays correctly. All previous buttons with the same value are blank. The height was also shrinking, but I fixed that with the 'Height' Setter above the triggers. To illustrate, when a new record is being created it looks like:
and after I've clicked buttons 1, 2, and 3 and 1 again:
I originally had the style referenced from the surrounding grid:
<Grid>
...
<Grid.Resources>
<Style BasedOn="{StaticResource YesNoToggleStyle}" TargetType="{x:Type ToggleButton}" />
</Grid.Resources>
But changing that so each ToggleButton references the style individually (<ToggleButton Style="{StaticResource YesNoToggleStyle}" ... />) hasn't made a difference.
I looked at Customizing the toggle state of a toggle button in wpf, and Override ToggleButton Style where the effect is the same, but they talk about external images, and my issues is all within wpf.
I also looked at the second answer to: i want to change backcolor of toggle button when toggle button ischecked and viceversa in WPF but a) I only have the blend + sketchflow preview that comes with VS2012, and b) i'm a total noob with blend and can't get from Select the "Checked State" to Reset the Background Color instruction in the answer (plus i'd be surprised if this task requires the blend tool).
Can anyone show me what to do to get multiple ToggleButtons to use the same style properly?
This works for me. Somewhere in Dictionary1.xaml:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="YesNoToggleStyle" TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource {x:Static ToolBar.ToggleButtonStyleKey}}">
<Style.Triggers>
<Trigger Property="IsChecked" Value="False">
<Setter Property="Background" Value="Crimson" />
<Setter Property="Content" Value="No"/>
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Background" Value="SpringGreen" />
<Setter Property="Content" Value="Yes"/>
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
Note, that style is based on ToolBar.ToggleButtonStyle.
<Grid>
<Grid.Resources>
<ResourceDictionary Source="pack://application:,,,/Dictionary1.xaml"/>
</Grid.Resources>
<ItemsControl ItemContainerStyle="{StaticResource YesNoToggleStyle}">
<ToggleButton />
<ToggleButton />
<ToggleButton />
</ItemsControl>
</Grid>
try to replace Content property to ContentTemplate:
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="Yes"/>
</DataTemplate>
</Setter.Value>
</Setter>
In my case I wanted to have a "Locked" ToggleButton in a common dll defined and reused across my Apps.
Here's my result, which worked for me. Maybe someone find it useful (put this in a Resourcedictionary.xaml):
<BitmapImage x:Key="LockedLock"
UriSource="/...;component/Resources/Lock_closed_16p.png" />
<BitmapImage x:Key="OpenLock"
UriSource="/...;component/Resources/Lock_open_16p.png" />
<Style x:Key="LockButton"
TargetType="ToggleButton">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Image Source="{DynamicResource OpenLock }"
Width="12"
Height="12"
Name="contentimage" />
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=ToggleButton , AncestorLevel=1, Mode=FindAncestor }, Path=IsChecked}"
Value="True">
<Setter Property="Image.Source"
TargetName="contentimage"
Value="{DynamicResource LockedLock }" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
Credits to:
Setting Button's Content to <Image> via Styles
Setter Target Name not recognized
I want to use a setter to set a default margin of all elements in my stackpanel, not just buttons but also textboxes and labels.
<StackPanel>
<StackPanel.Resources>
<Style TargetType="{x:Type Button}">
<Setter Property="Margin" Value="0,10,0,0"/>
</Style>
</StackPanel.Resources>
...
When I try to change above Button to Control or FrameworkElement (a derived type of each element) it doesn't work.
How can I fix this without having to specify 2 different Style elements with the same content but different x:Types on the TargetType?
You can do this with inheritance via Style's BasedOn attribute:
<StackPanel.Resources>
<Style x:Key="BaseStyle" TargetType="{x:Type FrameworkElement}">
<Setter Property="Margin" Value="0,10,0,0"/>
</Style>
<Style TargetType="{x:Type Label}" BasedOn="{StaticResource BaseStyle}" />
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource BaseStyle}" />
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource BaseStyle}" />
</StackPanel.Resources>
I have a context menu bound to a data source. For this context menu I have a DataTrigger to display a separator if the databound object has a value of "True" for the Separator property. This works well however it doesn't seem to pick up my global style for separators that I have in my application. The new separator appearance is different than the rest of my menu's. Is there a way to have it use the global style?
Below is the ContextMenu definition:
<ContextMenu
x:Key="ActionMenu"
ItemsSource="{Binding Source={StaticResource ActionMenuSource}}">
<ContextMenu.ItemContainerStyle>
<Style TargetType="{x:Type MenuItem}" BasedOn="{StaticResource {x:Type MenuItem}}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Separator}" Value="true">
<Setter Property="MenuItem.Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type MenuItem}">
<Separator Style="{DynamicResource {x:Static
MenuItem.SeparatorStyleKey}}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ContextMenu.ItemContainerStyle>
</ContextMenu>
Here are my global values for defining the Separator.
<Style x:Key="{x:Static MenuItem.SeparatorStyleKey}" TargetType="{x:Type Separator}">
<Setter Property="Template" Value="{DynamicResource tmp_ManhMenuItemSeparator}"/>
</Style>
<ControlTemplate x:Key="tmp_ManhMenuItemSeparator" TargetType="{x:Type Separator}">
<Rectangle Name="SepRect" StrokeThickness="1" Stroke="White"/>
</ControlTemplate>
To make a style global the key needs to be the same as the TargetType which is clearly not the case in your sample. Change your key to "{x:Type Separator}" and see if that works for you. You can also merge your two snippets together unless you have a particular need to split them out, e.g.
<Style x:Key="{x:Type Separator}" TargetType="{x:Type Separator}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Separator}">
<Rectangle Name="SepRect" StrokeThickness="1" Stroke="White"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Once you have done that you can probably strip down the first block of code. It looks like you are trying to make the menu manually use the style. If you make it global you don't need to do that, e.g.
<ContextMenu x:Key="ActionMenu" ItemsSource="{Binding Source={StaticResource ActionMenuSource}}"/>