I have a custom 3 state Button that is supposed to cycle between 3 different states (colours) as it is clicked. However the click handler I've written doesn't have any effect on the background colour of the Border within the ControlTemplate.
I'm probably missing something very simple, but I'd really appreciate a fresh pair of eyes to spot what it may be.
The ControlTemplate and Button.Click handler are below:
<Style x:Key="FilterButtonStyle" TargetType="{x:Type local:FilterButton}"
BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="ButtonBackground" BorderThickness="0" Padding="0"
Margin="0" CornerRadius="6"
Background="{StaticResource blueShader}" >
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Effect" Value="{StaticResource glowShadow}">
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Foreground" Value="{StaticResource textBrush}"/>
<Setter Property="Margin" Value="4,4,0,4"></Setter>
<Setter Property="Padding" Value="4"></Setter>
<Setter Property="Height" Value="55"></Setter>
<Setter Property="Width" Value="55"></Setter>
<Setter Property="FontSize" Value="10"/>
<Setter Property="FontWeight" Value="Normal"/>
<Setter Property="TextBlock.TextWrapping" Value="Wrap"></Setter>
<Setter Property="HasDisabledState" Value="True"></Setter>
<Setter Property="OnColour" Value="{StaticResource greenShader}"></Setter>
<Setter Property="OffColour" Value="{StaticResource blueShader}"></Setter>
<Setter Property="DisabledColour" Value="{StaticResource redShader}"></Setter>
</Style>
private void FilterButton_Click(object sender, RoutedEventArgs e)
{
if (!this.CanChangeState) { return; }
// Get child border element.
Border border = this.Template.LoadContent() as Border;
// Cycle through button states.
switch (this.ButtonState)
{
case ButtonStates.Off:
this.ButtonState = ButtonStates.On;
border.Background = this.OnColour;
break;
case ButtonStates.On:
if (this.HasDisabledState)
{
this.ButtonState = ButtonStates.Disabled;
border.Background = this.DisabledColour;
}
else
{
this.ButtonState = ButtonStates.Off;
border.Background = this.OffColour;
}
break;
case ButtonStates.Disabled:
this.ButtonState = ButtonStates.Off;
border.Background = this.OffColour;
break;
}
}
Never mind, I found that a better way of handling this was to use ControlTemplate triggers to change the Button colour based on the ButtonState property.
<Style x:Key="FilterButtonStyle" TargetType="{x:Type local:FilterButton}"
BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="ButtonBackground" BorderThickness="0" Padding="0" Margin="0" CornerRadius="6"
Background="{StaticResource blueShader}" >
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Effect" Value="{StaticResource glowShadow}">
</Setter>
</Trigger>
<Trigger Property="local:FilterButton.ButtonState" Value="On">
<Setter TargetName="ButtonBackground" Property="Background" Value="{StaticResource greenShader}"></Setter>
</Trigger>
<Trigger Property="local:FilterButton.ButtonState" Value="Off">
<Setter TargetName="ButtonBackground" Property="Background" Value="{StaticResource blueShader}"></Setter>
</Trigger>
<Trigger Property="local:FilterButton.ButtonState" Value="Disabled">
<Setter TargetName="ButtonBackground" Property="Background" Value="{StaticResource redShader}"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Foreground" Value="{StaticResource textBrush}"/>
<Setter Property="Margin" Value="4,4,0,4"></Setter>
<Setter Property="Padding" Value="4"></Setter>
<Setter Property="Height" Value="55"></Setter>
<Setter Property="Width" Value="55"></Setter>
<Setter Property="FontSize" Value="10"/>
<Setter Property="FontWeight" Value="Normal"/>
<Setter Property="TextBlock.TextWrapping" Value="Wrap"></Setter>
<Setter Property="HasDisabledState" Value="True"></Setter>
</Style>
Related
This question already has answers here:
WPF set border background in trigger
(1 answer)
WPF Trigger won't set property if set in Element
(3 answers)
Closed last year.
Below is the sample code of my WPF xaml file. My intention is to change the foreground of the label in the listboxitem to Red colour when the item is selected. However, no changes was seen on the foreground? What mistake had I done?
<UserControl.Resources>
<Style x:Key="WishlistListBoxStyle" TargetType="{x:Type ListBox}">
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="FontSize" Value="18"/>
<Setter Property="FontFamily" Value="Arial"/>
<Setter Property="Background" Value="#282C2F"/>
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType="ListBoxItem">
<Setter Property="Foreground" Value="White"/>
<Setter Property="Margin" Value="0"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border x:Name="WishlistBorder" Style="{DynamicResource WishlistBorderContent}">
<ContentPresenter />
</Border>
<ControlTemplate.Resources>
<Style x:Key="WishlistBorderContent" TargetType="Border">
<Setter Property="BorderThickness" Value="0 0 0 2"/>
<Setter Property="BorderBrush" Value="#50D3D3D3"/>
</Style>
</ControlTemplate.Resources>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="WishlistBorder" Property="BorderThickness" Value="2"/>
<Setter TargetName="WishlistBorder" Property="BorderBrush" Value="#63C5DA"/>
<Setter Property="Foreground" Value="Red"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="WishlistBorder" Property="Background" Value="#50D3D3D3"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<ListBox ItemsSource="{Binding SymbolList}" SelectedItem="{Binding SelectedSymbol}"
Style="{StaticResource WishlistListBoxStyle}" HorizontalContentAlignment="Stretch" Width="200" Padding="0">
<ListBox.ItemTemplate>
<DataTemplate>
<Label Content="{Binding}" Foreground="White"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I am trying to change the background color when button gets click/focused but there is not any change occurring.
<Style x:Key="btnInputForm" TargetType="{x:Type Button}">
<Setter Property="FontSize" Value="22"/>
<Setter Property="Background" Value="#2f772b"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="Width" Value="120"/>
<Setter Property="Height" Value="23"/>
<Setter Property="Button.RenderTransformOrigin" Value=".5,.5"/>
<Setter Property="TextElement.FontSize" Value="14" />
<Setter Property="TextElement.FontFamily" Value="Calibri" />
<Setter Property="Control.BorderBrush" Value="#085b09" />
<Setter Property="Control.BorderThickness" Value="1,1,1,1" />
<Setter Property="Margin" Value="3,10,3,3" />
<Setter Property="HorizontalAlignment" Value="Right" />
<Setter Property="VerticalAlignment" Value="Bottom" />
<Style.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="Background" Value="Yellow"/>
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="White"/>
<Setter Property="Foreground" Value="Black"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Green"/>
</Trigger>
<Trigger Property="IsFocused" Value="True">
<Setter Property="Background" Value="Red"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="Yellow"/>
</Trigger>
</Style.Triggers>
</Style>
And the button:
<Button Content="Click Me" Height="30" Width="100"></Button>
I am new to Styles and not sure on the best way to create a Button style to change the Foreground of IsMouseOver and IsPressed. I used a Border for a template because it has a CornerRadius and background and border properties. But Border does not have a Foreground property. Using Button as the template doesn't work well since the default look isn't being overridden.
What is a better way to style a Button template with Foreground behavior? Maybe using a label inside the border?
Here is the App.xaml:
<Application.Resources>
<Style TargetType="Button" x:Key="MyButton">
<Setter Property="SnapsToDevicePixels" Value="true"/>
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="MinHeight" Value="34"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Name="shortcutbutton"
BorderThickness="1"
BorderBrush="Black"
Background="Gray">
<ContentPresenter Margin="2"
HorizontalAlignment="Center"
VerticalAlignment="Center"
RecognizesAccessKey="True"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="shortcutbutton" Property="Background" Value="#FFDADADA" />
<Setter TargetName="shortcutbutton" Property="BorderBrush" Value="#EEEEEE" />
<!--<Setter TargetName="Border" Property="Foreground" Value="Black" />-->
</Trigger>
<Trigger Property="IsPressed" Value="true">
<Setter TargetName="shortcutbutton" Property="Background" Value="DarkGray" />
<Setter TargetName="shortcutbutton" Property="BorderBrush" Value="Black" />
<!--<Setter TargetName="Border" Property="Foreground" Value="Red" />-->
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Application.Resources>
And the xaml:
<StackPanel HorizontalAlignment="Center" Height="100" VerticalAlignment="Center" Width="100">
<Button Content="Button" Height="41" Style="{DynamicResource MyButton}"/>
</StackPanel>
You need to move your Triggers from the ControlTemplate to the Style. Something like this:
<Style TargetType="Button">
<Setter Property="SnapsToDevicePixels" Value="true"/>
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="MinHeight" Value="34"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Name="shortcutbutton"
BorderThickness="1"
BorderBrush="Black"
Background="Gray">
<ContentPresenter Margin="2"
HorizontalAlignment="Center"
VerticalAlignment="Center"
RecognizesAccessKey="True"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Foreground" Value="#FFDADADA" />
</Trigger>
<Trigger Property="IsPressed" Value="true">
<Setter Property="Foreground" Value="DarkGray" />
</Trigger>
</Style.Triggers>
</Style>
What you can do is set attached property of TextElement on the Border and like that every text element within your Border will be of that colour:
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="shortcutbutton" Property="Background" Value="#FFDADADA" />
<Setter TargetName="shortcutbutton" Property="BorderBrush" Value="#EEEEEE" />
<Setter TargetName="shortcutbutton" Property="TextElement.Foreground" Value="White"/>
</Trigger>
...
</ControlTemplate.Triggers>
I've got DataGrid with several DataGridTextColumn's, one of which is editable.
I need to intercept TextChanged event for the cell that is being edited.
I've tried editing style and adding
<EventSetter Event="TextChanged" Handler="TaskDescription_TextChanged"/>
but I'm getting
Cannot find the Style Event 'TextChanged' on the type 'System.Windows.Controls.DataGridCell'
Is there an easy way to get notified of the text change in DataGridTextColumn except by Two-Way binding?
Here's the XAML code:
<Style x:Key="CenteredTextColumn" TargetType="{x:Type DataGridCell}">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Grid Height="30">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<ContentPresenter VerticalAlignment="Center" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="VerticalAlignment" Value="Stretch"/>
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="Foreground" Value="Black"/>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="{StaticResource SelectedCellBackground}"/>
<Setter Property="Foreground" Value="White"/>
<!--<Setter Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>-->
</Trigger>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<!--<Setter Property="BorderBrush" Value="{DynamicResource {x:Static DataGrid.FocusBorderBrushKey}}"/>-->
</Trigger>
<Trigger Property="IsEditing" Value="True">
<Setter Property="Background" Value="Transparent"/>
</Trigger>
</Style.Triggers>
</Style>
and the EventSetter:
<Style x:Key="ProjectInfoEditeableCell" TargetType="{x:Type DataGridCell}" BasedOn="{StaticResource CenteredTextColumn}">
<EventSetter Event="TextChanged" Handler="TaskDescription_TextChanged"/>
</Style>
I've created template for combobox but it has strange view, data is not displaying:
Here is XAML code:
<Style TargetType="{x:Type ComboBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ComboBox}">
<Border Background="{TemplateBinding Background}" x:Name="Bd" BorderBrush="Gray" BorderThickness="2" CornerRadius="2">
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" TargetName="Bd"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
<Trigger Property="IsFocused" Value="true">
<Setter Property="BorderBrush" Value="Blue" TargetName="Bd"/>
<Setter Property="BorderThickness" Value="2"/>
</Trigger>
<Trigger Property="IsFocused" Value="false">
<Setter Property="BorderBrush" Value="Gray" TargetName="Bd"/>
<Setter Property="BorderThickness" Value="2"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
What i missed here?
Your template creates near to nothing which makes the default one work, i.e. there is no items popup, and there is no ContentPresenter for the selected item either. Have a look at the default template and you will see exactly what you are missing (Here is a question explaining where to get them).