Include a Button in a TextBox - wpf

I want to add a little Button, which removes all the text in the TextBox. Is it possible to put this "Remove"-Button into the TextBox (like in the iPhone Textboxs)?
I hope after your help it looks like that:
I played something with the controltemplate but didn't get the wished result.
One way to solve this problem could be to use negative margins of the button, but i think that isn't a clean solution.
Thank you!

Got something using interactivity, but you probably can manage without:
<LinearGradientBrush x:Key="TextBoxBorder" EndPoint="0,20" MappingMode="Absolute" StartPoint="0,0">
<GradientStop Color="#ABADB3" Offset="0.05" />
<GradientStop Color="#E2E3EA" Offset="0.07" />
<GradientStop Color="#E3E9EF" Offset="1" />
</LinearGradientBrush>
<Style x:Key="ExtendedTextBoxTemplate" BasedOn="{x:Null}" TargetType="{x:Type TextBox}">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" />
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}" />
<Setter Property="BorderBrush" Value="{StaticResource TextBoxBorder}" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Padding" Value="1" />
<Setter Property="AllowDrop" Value="true" />
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst" />
<Setter Property="Stylus.IsFlicksEnabled" Value="False" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<!-- Here i just wrap the content in a grid and place a button on the right, needs to be styled though -->
<Grid>
<Microsoft_Windows_Themes:ListBoxChrome x:Name="Bd"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
RenderMouseOver="{TemplateBinding IsMouseOver}"
RenderFocused="{TemplateBinding IsKeyboardFocusWithin}" SnapsToDevicePixels="true">
<ScrollViewer x:Name="PART_ContentHost"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</Microsoft_Windows_Themes:ListBoxChrome>
<Button Content="X" HorizontalAlignment="Right">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<ta:ClearTextAction
Target="{Binding RelativeSource={RelativeSource TemplatedParent}}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Background" TargetName="Bd"
Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" />
<Setter Property="Foreground"
Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
class ClearTextAction : TriggerAction<Button>
{
public static readonly DependencyProperty TargetProperty =
DependencyProperty.Register("Target", typeof(TextBox), typeof(ClearTextAction), new UIPropertyMetadata(null));
public TextBox Target
{
get { return (TextBox)GetValue(TargetProperty); }
set { SetValue(TargetProperty, value); }
}
protected override void Invoke(object parameter)
{
Target.Clear();
}
}
You could make the button only show upon TextBox-MouseOver by adding this style to it:
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Visibility" Value="Hidden" />
<Style.Triggers>
<DataTrigger
Binding="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsMouseOver}"
Value="True">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>

Assuming you don't want text or the cursor to disappear behind the button, the only clean way is to re-template the TextBox. If you're not really fussed about that, then you could just do this:
<Grid>
<TextBox/>
<Image ... VerticalAlignment="Center" HorizontalAlignment="Right" Margin="0 0 3 0"/>
</Grid>

You can easily derive from textbox and create your own textbox with the functionality you want.That is the flexibility that wpf provides.See the link below
http://davidowens.wordpress.com/2009/02/18/wpf-search-text-box/

Related

WPF. Prevent checkbox inside button from firing click event

I have a button with a checkbox inside in WPF. I want to be able to check the checkbox without firing the click event of the button.
My problem is that, currently, the click event is fired whether I press the checkbox itself or its label, behavior I don't want. I only want to raise the click event if I press somewhere in the red zone.
Is there a way to prevent this?
This is my code by now:
Style for the checkbox:
<Style x:Key="FilledCheckBox" TargetType="{x:Type CheckBox}">
<Setter Property="Foreground" Value="Gray"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type CheckBox}">
<BulletDecorator Background="Transparent">
<BulletDecorator.Bullet>
<Border x:Name="Border"
Width="15"
Height="15"
CornerRadius="1"
BorderThickness="1">
<Border.BorderBrush>
<SolidColorBrush Color="Gray"/>
</Border.BorderBrush>
<Border.Background>
<SolidColorBrush Color="White"/>
</Border.Background>
</Border>
</BulletDecorator.Bullet>
<ContentPresenter Margin="5,0,0,0"
VerticalAlignment="Top"
HorizontalAlignment="Left"
RecognizesAccessKey="True" />
</BulletDecorator>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Background" TargetName="Border" Value="Green"/>
<Setter Property="BorderBrush" TargetName="Border" Value="Green"/>
<Setter Property="Foreground" Value="Green"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Style for the button (with the checkbox inside):
<Style x:Key="RoundCornerButtonWithCheck" TargetType="{x:Type Button}">
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Width" Value="120"/>
<Setter Property="Height" Value="30"/>
<Setter Property="Padding" Value="1"/>
<Setter Property="Button.Effect">
<Setter.Value>
<DropShadowEffect Color="Black" Direction="280" ShadowDepth="2" BlurRadius="5" Opacity="0.2" />
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid x:Name="grid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="120"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border x:Name="border" CornerRadius="15" BorderBrush="Black" BorderThickness="0" Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center"
TextElement.FontWeight="SemiBold">
</ContentPresenter>
</Border>
<CheckBox x:Name="checkbox" Grid.Column="0" VerticalAlignment="Center" Margin="20,0,0,0" Style="{StaticResource FilledCheckBox}"></CheckBox>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" TargetName="border">
<Setter.Value>
<SolidColorBrush Color="Gold" />
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderBrush" TargetName="border" Value="#FF33962B"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" TargetName="grid" Value="0.25"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The button in the template:
<Button Name="deleteButton" Style="{StaticResource RoundCornerButtonWithCheck}" Content="{Binding Source={x:Static localization:Resources.Delete}, Converter={StaticResource CharacterCasingConverter}}" VerticalAlignment="Center" HorizontalAlignment="Left" Background="Red" Foreground="White" Margin="80,0,80,30" Click="DeleteClick"></Button>
Is there a way to prevent this?
You can't really prevent the built-in Button control itself from handling the click without cancelling the PreviewMouseLeftButtonDown event but you can implement the event handler to ignore clicks on the CheckBox:
private void SaveClick(object sender, RoutedEventArgs e)
{
if (!(e.OriginalSource is CheckBox))
{
//handle click outside the CheckBox...
}
}

Custom button style is not working?

I'm trying to style a button, but it ends up not showing when I apply the custom style, only its content (the button's text) is visible. This is how I declare my style:
<Color x:Key="NormalColor" A="255" R="60" G ="158" B="184"/>
<Color x:Key="HoverColor" A="255" R="74" G ="177" B="204"/>
<Color x:Key="PressedColor" A="255" R="26" G ="115" B="138"/>
<SolidColorBrush x:Key="NormalBrush" Color="{StaticResource NormalColor}" />
<SolidColorBrush x:Key="HoverBrush" Color="{StaticResource HoverColor}" />
<SolidColorBrush x:Key="PressedBrush" Color="{StaticResource PressedColor}" />
<Style x:Key="FlatButton" TargetType="Button">
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="FontFamily" Value="Segoe UI"/>
<Setter Property="Background" Value="{StaticResource NormalBrush}"/>
<Setter Property="Foreground" Value="#000000"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Name="Content"/>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{StaticResource HoverBrush}" />
<Setter Property="Foreground" Value="#000000" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="{StaticResource PressedBrush}" />
<Setter Property="Foreground" Value="#000000" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" Value="{StaticResource NormalBrush}" />
<Setter Property="Foreground" Value="#000000" />
<Setter Property="Opacity" Value="0.5" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
And here is how I use it:
<Button Content="Connect" Command="model:GlobalCommands.ConnectToDBCommand" Style="{StaticResource FlatButton}"/>
Can anyone tell me where I went wrong with this?
Thank you!
There is nothing in your ControlTemplate that would use Background. Put your ContentPresenter inside Border (for example) and use TemplateBinding to bind its Background
<Border Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Name="Content"/>
</Border>
Adding to #dkozl's answer, you should add TemplateBindings to any properties within the Button.ControlTemplate that you may want to set from outside the Button.ControlTemplate:
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding
BorderThickness}" Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
Then you could do this:
<Button Content="Connect" Command="model:GlobalCommands.ConnectToDBCommand"
Style="{StaticResource FlatButton}" BorderBrush="Blue" BordeThickness="5" />

How to change button background in WPF xaml?

Hello guys I'm new to WPF and XAML.
I'm stuck on changing the button background, image, colour or whatever, it just keeps being white.
It just shows the background when I double click on it in the visual editor so I can type some text on it, then it becomes white again.
Any clue about what I'm doing wrong?
<Button Margin="5,-7,5,-1" Width="59" Content="{Binding PlayContent}" x:Name="PlayPause" HorizontalAlignment="Center" cal:Bind.AtDesignTime="True">
<Button.Background>
<ImageBrush ImageSource="resources/main_play_normal.png"/>
</Button.Background>
</Button>
thanks
You just need to use style and template to modify your button behavior.
Here is a Metro Style for WPF Button try to use it :
<Style
x:Key="ButtonFocusVisual">
<Setter
Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle Margin="2" SnapsToDevicePixels="true" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="MetroButton" TargetType="{x:Type Button}">
<Setter Property="FocusVisualStyle" Value="{StaticResource ButtonFocusVisual}"/>
<Setter Property="Background" Value="#EEEEEEEE"/>
<Setter Property="Foreground" Value="Black"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Padding" Value="10 5"/>
<Setter Property="FontSize" Value="14" />
<Setter Property="BorderThickness" Value="2" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<Border
x:Name="Border"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}" />
<ContentPresenter
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding Padding}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
RecognizesAccessKey="True" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter Property="OpacityMask" Value="#AA888888"/>
<Setter Property="Margin" Value="2 1" />
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderThickness" Value="0"/>
<!--<Setter Property="Background" Value="DimGray"/>-->
<Setter Property="Foreground" Value="White"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="#ADADAD"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
EDIT
Try to use this style:
<Style x:Key="GreenButton" TargetType="Button">
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="Margin" Value="2"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="Background" >
<Setter.Value>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1" >
<GradientStop Color="#FF3F9542" Offset="0.85"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Name="border"
BorderThickness="0"
Padding="4,2"
BorderBrush="LightGray"
CornerRadius="2"
Background="{TemplateBinding Background}">
<Grid >
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center" Name="contentShadow" >
</ContentPresenter>
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center" Name="content"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border" Property="BorderBrush" Value="#FF4788c8" />
<Setter Property="Foreground" Value="White" />
<Setter Property="Cursor" Value="Hand" />
<Setter Property="Background" Value="#FF429C46"/>
</Trigger>
<Trigger Property="IsDefaulted" Value="True">
<Setter TargetName="border" Property="BorderBrush" Value="#FF282828" />
</Trigger>
<Trigger Property="IsFocused" Value="True">
<Setter TargetName="border" Property="BorderBrush" Value="#FF282828" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="border" Property="Opacity" Value="0.7" />
<Setter Property="Foreground" Value="Black" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Then you just apply that style like this :
<Button x:Name="m_Button" Height="35" Content="Submit" Style="{StaticResource GreenButton}" IsEnabled="True" Click="m_Button_Click"/>
*If want to set image as background use
<Button x:Name="bt_cam" HorizontalAlignment="Left" Margin="5,-7,5,-1" Height="80"Width="59" VerticalAlignment="Top" Click="Button_Click" >
<Button.Effect>
<DropShadowEffect Opacity="0.3" ShadowDepth="12" />
</Button.Effect>
<StackPanel>
<Image x:Name="cam" Source="resources/main_play_normal.png" />
</StackPanel>
</Button>
If want to set background color,then remove the stackpannel and add background color on
button
You need to change your code like this,
<Button Margin="5,-7,5,-1" Width="59" x:Name="PlayPause">
<Image Source="resources/main_play_normal.png"/>
</Button>

To show Tooltip on focus of a textbox until user puts data into textbox

I have a complex WPF application based on MVVM. I want to create an assistance mode for my application.So for example I am thinking that a customized tootip will open (on a textbox) when user opens the screen and remain opened until user puts some data into it. As user puts data,the focus will automatically shift to the next control and another tooltip for that control will open and this way the flow will go on.One thing, I want to code in XAML only..Any suggestion friends ???
I think it will be easier to modify the template of text box with some help from attached properties.
Make a class to hold helper attached properties. Let's call it Assistance and it will have two attached properties:
AssistanceTipContent of type object.
IsAssistanceActive of type bool.
Then the custom Style/Template for Text Box (based on default Aero theme):
<!--Add this xmlns definition to the root of the file-->
xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"
....
<!--Then in resources-->
<LinearGradientBrush x:Key="TextBoxBorder" EndPoint="0,20" MappingMode="Absolute" StartPoint="0,0">
<GradientStop Color="#ABADB3" Offset="0.05"/>
<GradientStop Color="#E2E3EA" Offset="0.07"/>
<GradientStop Color="#E3E9EF" Offset="1"/>
</LinearGradientBrush>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
<Setter Property="BorderBrush" Value="{StaticResource TextBoxBorder}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Padding" Value="1"/>
<Setter Property="AllowDrop" Value="true"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/>
<Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Grid>
<Microsoft_Windows_Themes:ListBoxChrome x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderFocused="{TemplateBinding IsKeyboardFocusWithin}" SnapsToDevicePixels="true">
<ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Microsoft_Windows_Themes:ListBoxChrome>
<Popup x:Name="AssistanceTip"
IsOpen="False"
AllowsTransparancy="True">
<!--TODO: Add Background/BorderBrush/BorderThicknes to this Border so it matches ToolTip style-->
<Border>
<ContentControl Content="{Binding Path=(Assistance.AssistanceTipContent), RelativeSource={RelativeSource TemplatedParent}}"/>
</Border>
</Popup>
</Grid>
<ControlTemplate.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, IsKeyboardFocusWithin}" Value="True"/>
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Text}" Value=""/>
<Condition Binding="{Binding Path=(Assistance.IsAssistanceActive), RelativeSource={RelativeSource Self}}" Value="True"/>
</MultiDataTrigger.Conditions>
<Setter TargetName="AssistanceTip" Property="IsOpen" Value="True"/>
</MultiDataTrigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Now your use will be something like:
<TextBox local:Assistance.AssistanceTipContent="Some text to help the user"
local:Assistance.IsAssistanceActive="{Binding IsAssistanceModeActive}"
..../>
This removes data triggers (to view model data) from styles and makes it quite generic approach.
[The change of focus is not handled here, I understand that you've accomplished that already.]

Elegantly override style of ComboBox's ToggleButton in WPF

I have a question regarding how to elegantly override an arbitrary element deep inside a control's visual tree. I also have attempted to resolve it in a few different ways, but I've run into several problems with each. Usually when I try three different paths and fail at each one I go downstairs, have a coffee, and ask someone smarter than myself. So here I am.
Specifics:
I want to flatten the style of a combo box so that it will not draw attention to itself. I want it to be similar to Windows.Forms.ComboBox's FlatStyle I want it to look the same on Windows 7 and XP.
Mainly, I want to change the look of a ComboBox's ToggleButton.
I could just use Blend and rip the control template's guts out and manually change them. That doesn't sound very appetizing to me.
I tried using a style to override the ToggleButton's background, but it turns out that the whole ComboBox control is actually a front for a ToggleButton.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ComboBoxExpiriment2.MainWindow"
x:Name="Window"
xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Classic" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="MainWindow"
Width="204" Height="103">
<Grid x:Name="LayoutRoot">
<ComboBox HorizontalAlignment="Left" Margin="32,26.723,0,0" Width="120" VerticalAlignment="Top" Height="21.277">
<ComboBox.Style>
<Style>
<Setter Property="ToggleButton.Background" Value="Green" />
</Style>
</ComboBox.Style>
</ComboBox>
</Grid>
So I gave up and ripped it using Blend. I found that it's actually a Style called ComboBoxTransparentButtonStyle with a target type of ToggleButton. The style sets a ControlTemplate that uses a DockPanel that has a "Microsoft_Windows_Themes:ClassicBorderDecorator" type set to the right, and that's what we're actually trying to control. (Are you with me so far?)
Here's the pic:
<Style x:Key="ComboBoxTransparentButtonStyle" TargetType="{x:Type ToggleButton}">
<Setter Property="MinWidth" Value="0"/>
<Setter Property="MinHeight" Value="0"/>
<Setter Property="Width" Value="Auto"/>
<Setter Property="Height" Value="Auto"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="{x:Static Microsoft_Windows_Themes:ClassicBorderDecorator.ClassicBorderBrush}"/>
<Setter Property="BorderThickness" Value="2"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<DockPanel SnapsToDevicePixels="true" Background="{TemplateBinding Background}" LastChildFill="false">
<Microsoft_Windows_Themes:ClassicBorderDecorator x:Name="Border" Width="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}" DockPanel.Dock="Right" Background="Green" BorderBrush="{TemplateBinding BorderBrush}" BorderStyle="None" BorderThickness="{TemplateBinding BorderThickness}">
<Path Fill="{TemplateBinding Foreground}" HorizontalAlignment="Center" VerticalAlignment="Center" Data="{StaticResource DownArrowGeometry}"/>
</Microsoft_Windows_Themes:ClassicBorderDecorator>
</DockPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="true">
<Setter Property="BorderStyle" TargetName="Border" Value="AltPressed"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlDarkBrushKey}}"/>
</Trigger>
</Style.Triggers>
</Style>
Arg. Isn't WPF a blast?
So I extracted the style ComboBoxTransparentButtonStyle and dropped it into another project's application.resources. Problem is I can't apply that style to a ComboBox because the style I extracted has a targetType of ToggleButton, so the TargeTypes don't match.
tl;dr how would you guys do it?
There isn't an elegant solution for this. The best you can do is override the style for the entire ComboBox so that you can change the style it sets for the ToggleButton.
You can use Blend to get the styles, however that probabliy isn't the easiest way. If you have Blend installed, go to "[Program files or where Blend is installed]\SystemThemes\WPF\areo.normalcolor.xaml".
A Working Solution
Hi, this style satisfies your needs, feel free to edit it as you need:
<SolidColorBrush x:Key="WindowBackgroundBrush" Color="White" />
<SolidColorBrush x:Key="MainColor" Color="DeepSkyBlue"/>
<SolidColorBrush x:Key="MainColorLight" Color="LightSkyBlue"/>
<SolidColorBrush x:Key="MainColorDark" Color="#00A7DF"/>
<SolidColorBrush x:Key="BorderMainBrush" Color="LightGray"/>
<SolidColorBrush x:Key="BorderDarkMainBrush" Color="#C0C0C0"/>
<SolidColorBrush x:Key="BackgroundGrayDark" Color="#FFEFEFEF"/>
<SolidColorBrush x:Key="BackgroundGrayLight" Color="#F5F5F5"/>
<SolidColorBrush x:Key="ForegroundDisabledBrush" Color="DimGray"/>
<SolidColorBrush x:Key="ForegroundBrush" Color="Black"/>
<LinearGradientBrush x:Key="FormBackgroundBrush"
EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFFFFD" Offset="0.31" />
<GradientStop Color="#FFF8F8F8" Offset="1" />
</LinearGradientBrush>
<ControlTemplate x:Key="ComboBoxToggleButton" TargetType="ToggleButton">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver"/>
<VisualState x:Name="Pressed"/>
<VisualState x:Name="Disabled"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="Border" SnapsToDevicePixels="True" Grid.ColumnSpan="2" Background="{DynamicResource BackgroundGrayDark}" BorderBrush="{DynamicResource BorderDarkMainBrush}" BorderThickness="1" />
<Border x:Name="Border2" Grid.Column="0" SnapsToDevicePixels="True" Margin="1" Background="{StaticResource WindowBackgroundBrush}" BorderBrush="{DynamicResource BorderDarkMainBrush}" BorderThickness="0,0,1,0" />
<Path x:Name="Arrow" Grid.Column="1" Data="M 0 0 L 4 4 L 8 0 Z" Fill="DimGray" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="ToggleButton.IsMouseOver" Value="true">
<Setter Property="Background" TargetName="Border" Value="{DynamicResource MainColor}" />
<Setter Property="BorderBrush" TargetName="Border" Value="{DynamicResource MainColor}" />
<Setter Property="BorderBrush" TargetName="Border2" Value="{DynamicResource MainColor}" />
<Setter Property="Fill" TargetName="Arrow" Value="White" />
</Trigger>
<Trigger Property="ToggleButton.IsChecked" Value="true">
<Setter Property="Background" TargetName="Border" Value="{DynamicResource MainColorDark}" />
<Setter Property="BorderBrush" TargetName="Border" Value="{DynamicResource MainColorDark}" />
<Setter Property="BorderBrush" TargetName="Border2" Value="{DynamicResource MainColorDark}" />
<Setter Property="Fill" TargetName="Arrow" Value="White" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" TargetName="Border" Value="{DynamicResource BackgroundGrayLight}" />
<Setter Property="BorderBrush" TargetName="Border" Value="{StaticResource BorderMainBrush}" />
<Setter Property="Foreground" Value="{StaticResource ForegroundDisabledBrush}" />
</Trigger>
<DataTrigger Binding="{Binding IsKeyboardFocusWithin, RelativeSource={RelativeSource Mode=TemplatedParent}, Mode=OneWay}" Value="True">
<Setter Property="Background" TargetName="Border" Value="{DynamicResource MainColorLight}" />
<Setter Property="BorderBrush" TargetName="Border" Value="{DynamicResource MainColorLight}" />
<Setter Property="BorderBrush" TargetName="Border2" Value="{DynamicResource MainColorLight}" />
<Setter Property="Fill" TargetName="Arrow" Value="White" />
</DataTrigger >
</ControlTemplate.Triggers>
</ControlTemplate>
<ControlTemplate x:Key="ComboBoxTextBox" TargetType="TextBox">
<Border x:Name="PART_ContentHost" Background="{TemplateBinding Background}" Focusable="False" />
</ControlTemplate>
<Style TargetType="ComboBox">
<Setter Property="Validation.ErrorTemplate" Value="{x:Null}" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="IsEditable" Value="True"/>
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto" />
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto" />
<Setter Property="ScrollViewer.CanContentScroll" Value="true" />
<Setter Property="Margin" Value="2" />
<Setter Property="MinHeight" Value="20" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ComboBox">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver"/>
<VisualState x:Name="Disabled"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ToggleButton x:Name="ToggleButton" Grid.Column="2" ClickMode="Press" Focusable="false"
IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
Template="{StaticResource ComboBoxToggleButton}"/>
<ContentPresenter Margin="3,3,23,3" Content="{TemplateBinding SelectionBoxItem}"
ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"
HorizontalAlignment="Left" IsHitTestVisible="False" x:Name="ContentSite"
VerticalAlignment="Center" />
<TextBox Style="{x:Null}" x:Name="PART_EditableTextBox" Margin="3,3,23,3" Background="Transparent"
Focusable="True" HorizontalAlignment="Left" IsReadOnly="{TemplateBinding IsReadOnly}"
Template="{StaticResource ComboBoxTextBox}" VerticalAlignment="Center" Visibility="Hidden" />
<Popup AllowsTransparency="True" Focusable="False" IsOpen="{TemplateBinding IsDropDownOpen}" x:Name="Popup" Placement="Bottom" PopupAnimation="Fade">
<Grid MaxHeight="{TemplateBinding MaxDropDownHeight}" MinWidth="{TemplateBinding ActualWidth}" x:Name="DropDown" SnapsToDevicePixels="True">
<Border x:Name="DropDownBorder" Background="White" BorderBrush="{StaticResource BorderDarkMainBrush}" BorderThickness="1" CornerRadius="0" />
<ScrollViewer Margin="2" SnapsToDevicePixels="True">
<StackPanel KeyboardNavigation.DirectionalNavigation="Contained" IsItemsHost="True" TextBlock.Foreground="Black" />
</ScrollViewer>
</Grid>
</Popup>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="HasItems" Value="false">
<Setter Property="MinHeight" TargetName="DropDownBorder" Value="95" />
</Trigger>
<Trigger Property="IsGrouping" Value="true">
<Setter Property="ScrollViewer.CanContentScroll" Value="false" />
</Trigger>
<Trigger Property="IsEditable" Value="true">
<Setter Property="IsTabStop" Value="false" />
<Setter Property="Visibility" TargetName="PART_EditableTextBox" Value="Visible" />
<Setter Property="Visibility" TargetName="ContentSite" Value="Hidden" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
</Style.Triggers>
</Style>
Note the DataTrigger part inside the toggle button style, it hooks to its templated parent's IsKeyboardFocusWithin property istead of IsFocused property, because the last one won't work if you set the ComboBox.IsEditable to True as I did in this style.
<DataTrigger Binding="{Binding IsKeyboardFocusWithin, RelativeSource={RelativeSource Mode=TemplatedParent}, Mode=OneWay}" Value="True">
<Setter Property="Background" TargetName="Border" Value="{DynamicResource MainColorLight}" />
<Setter Property="BorderBrush" TargetName="Border" Value="{DynamicResource MainColorLight}" />
<Setter Property="BorderBrush" TargetName="Border2" Value="{DynamicResource MainColorLight}" />
<Setter Property="Fill" TargetName="Arrow" Value="White" />
</DataTrigger >

Resources