I would like to mimic a style for a group of ToggleButtons as in the below image. Only one of the buttons can be "Checked" at any time.
My question is related to styling:
I'd like to have rounded corners on the leftmost button and the rightmost button as in the image but if there is a button between (like in the image), that should not have rounded corners. Sometimes there might only be two buttons to toggle.
I need style for different states: "Normal/Unchecked", "Mouseover", "Pressed" and "Checked" at the minimum.
The current control I am using for this is done like this:
<StackPanel Orientation="Horizontal" >
<RadioButton Style="{StaticResource {x:Type ToggleButton}}" Content="All" Padding="12,8,12,8" GroupName="View" />
<RadioButton Style="{StaticResource {x:Type ToggleButton}}" Content="Geolocated" Padding="12,8,12,8" GroupName="View" />
<RadioButton Style="{StaticResource {x:Type ToggleButton}}" Content="Non Geolocated" Padding="12,8,12,8" GroupName="View" />
</StackPanel>
In the StackPanel Resources I am trying to set Style for ToggleButton but I'm pretty lost how to achieve the result as in the image above.
This may not be the easiest/best approach, but I took a stab at knocking up some ControlTemplates using Kaxaml, to produce something that looks like this:
You could store these templates in a ResourceDictionary and apply them when required, or use them if you were building your button list on the fly.
I actually created three slightly different styles, one for the left and right buttons, and one for the middle (you may be able to simplify this with extending/inheriting styles). Some repeated code omitted.
<Grid>
<Grid.Resources>
<!-- Brushes for colours/backgrounds -->
<SolidColorBrush x:Key="FontBrush" Color="#DDDDDD"/>
<LinearGradientBrush x:Key="BgBrush1" StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0" Color="#888888"/>
<GradientStop Offset="1" Color="#222222"/>
</LinearGradientBrush>
<SolidColorBrush x:Key="BorderBrush1" Color="#333333"/>
<LinearGradientBrush x:Key="CheckedBrush" StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0" Color="#555555"/>
<GradientStop Offset="1" Color="#111111"/>
</LinearGradientBrush>
<!-- Left Button Template -->
<ControlTemplate x:Key="ToggleButtonLeft" TargetType="{x:Type ToggleButton}">
<Border
Name="Border"
Background="{StaticResource BgBrush1}"
BorderBrush="{StaticResource BorderBrush1}"
BorderThickness="1"
CornerRadius="5,0,0,5">
<ContentPresenter
HorizontalAlignment="Center"
Margin="{TemplateBinding Padding}"
VerticalAlignment="Center"
Content="{TemplateBinding Content}"
TextBlock.FontWeight="Bold"
TextBlock.Foreground="{StaticResource FontBrush}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="ToggleButton.IsMouseOver" Value="true">
<Setter TargetName="Border" Property="Background" Value="#808080"/>
</Trigger>
<Trigger Property="IsChecked" Value="true">
<Setter TargetName="Border" Property="Background" Value="{StaticResource CheckedBrush}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<!-- Middle Button(s) Template -->
<ControlTemplate x:Key="ToggleButtonMid" TargetType="{x:Type ToggleButton}">
<Border
Name="Border"
Background="{StaticResource BgBrush1}"
BorderBrush="{StaticResource BorderBrush1}"
BorderThickness="0,1,0,1"
CornerRadius="0" />
<!-- Other code identical to Left Button Template -->
</ControlTemplate>
<!-- Right Button Template -->
<ControlTemplate x:Key="ToggleButtonRight" TargetType="{x:Type ToggleButton}">
<Border
Name="Border"
Background="{StaticResource BgBrush1}"
BorderBrush="{StaticResource BorderBrush1}"
BorderThickness="1"
CornerRadius="0, 5, 5, 0" />
<!-- Other code identical to Left Button Template -->
</ControlTemplate>
</Grid.Resources>
<!-- Example Usage -->
<Grid Background="#555555">
<StackPanel Height="25" Orientation="Horizontal" Margin="5">
<RadioButton Content="All" GroupName="View" Padding="2" Template="{DynamicResource ToggleButtonLeft}"/>
<RadioButton Content="Geolocated" GroupName="View" Padding="2" Template="{DynamicResource ToggleButtonMid}"/>
<RadioButton Content="Non Geolocated" GroupName="View" Padding="2" Template="{DynamicResource ToggleButtonRight}"/>
</StackPanel>
</Grid>
</Grid>
You would have to add additional Triggers etc. for the IsPressed state, and any others required (e.g IsEnabled).
Related
I'm made a style for DataGridColumnHeader. Most of it is working, but I get second Border through my header text and I don't know how to solve this. See the image below for the result I get:
I only want the one border that's below the text. This is the style I've made:
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
<Grid Name="HeaderGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="14" />
</Grid.ColumnDefinitions>
<Border
x:Name="BackgroundBorder"
Grid.ColumnSpan="2"
BorderBrush="{DynamicResource Dark}"
BorderThickness="0,0,1,1"/>
<ContentPresenter
Grid.Column="0"
Margin="6,3,6,3"
VerticalAlignment="Center" />
<Path
x:Name="SortArrow"
Grid.Column="1"
Width="6"
Height="4"
Margin="0,0,8,0"
VerticalAlignment="Center"
Data="M 0 4 L 3.5 0 L 7 4 Z"
Fill="{DynamicResource Dark}"
RenderTransformOrigin="0.5,0.4"
Stretch="Fill"
Visibility="Collapsed" />
<Thumb
x:Name="PART_RightHeaderGripper"
Grid.Column="1"
HorizontalAlignment="Right"
Cursor="SizeWE">
<Thumb.Style>
<Style TargetType="{x:Type Thumb}">
<Setter Property="Width" Value="2" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<Border Background="Transparent" BorderBrush="Transparent" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Thumb.Style>
</Thumb>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="SortDirection" Value="Ascending">
<Setter TargetName="SortArrow" Property="Visibility" Value="Visible" />
<Setter TargetName="SortArrow" Property="RenderTransform">
<Setter.Value>
<RotateTransform Angle="180" />
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="SortDirection" Value="Descending">
<Setter TargetName="SortArrow" Property="Visibility" Value="Visible" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Can someone show me where I went wrong with the style I made?
EDIT:
I've put all the elements inside the border, but this doesn't seem to fix it.
When I give the border a different thickness, this is the result:
BorderThickness="0,2,1,4"
Both the top and bottom border appear twice.
Giving the header a MinHeight removes the double borders. This doesn't seem like a perfect fix, but works for now.
I recommend you take a careful look at how the original template works.
It's not clear what you're trying to achieve, but you need two thumbs for resizing.
On the following page
https://learn.microsoft.com/en-us/dotnet/framework/wpf/controls/datagrid-styles-and-templates
Search on columnheader then cycle through the hits until you see markup looks like:
<!--Style and template for the DataGridColumnHeader.-->
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="VerticalContentAlignment"
Value="Center" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
<Grid>
<Border x:Name="columnHeaderBorder"
BorderThickness="1"
Padding="3,0,3,0">
<Border.BorderBrush>
<LinearGradientBrush EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource BorderLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource BorderDarkColor}"
Offset="1" />
</LinearGradientBrush>
</Border.BorderBrush>
<Border.Background>
<LinearGradientBrush EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="1" />
</LinearGradientBrush>
</Border.Background>
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Border>
<Thumb x:Name="PART_LeftHeaderGripper"
HorizontalAlignment="Left"
Style="{StaticResource ColumnHeaderGripperStyle}" />
<Thumb x:Name="PART_RightHeaderGripper"
HorizontalAlignment="Right"
Style="{StaticResource ColumnHeaderGripperStyle}" />
</Grid>
</ControlTemplate>
</Setter.Value>
Notice particularly:
You need a PART_LeftHeaderGripper thumb.
Both thumbs are arranged using horizontalalignment left and right which would stop them filling the cell like yours does.
There is a width set in the style.
As a final piece of advice.
I strongly recommend you start with a working copy of a standard control template. Then carefully make small iterative changes. That way, when it breaks you know what broke it.
I am using custom ComboBox with style, I want to set width of a Popup dynamically via coading so that to auto adjust the width of popup
so I wanted to change Popup like second image dynamically(whatever may be thesize of ComboBox)
I am using style as follows
<Style x:Key="ComboBoxStyle" TargetType="{x:Type ComboBox}">
<Setter Property="Foreground" Value="#666666"/>
<Setter Property="FontFamily" Value="Arial"/>
<Setter Property="FontSize" Value="13"/>
<Setter Property="Height" Value="28"/>
<Setter Property="BorderThickness" Value="1.5"/>
<Setter Property="Padding" Value="4,3"/>
<Setter Property="Margin" Value="5"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ComboBox}">
<Grid>
<Popup Margin="1" x:Name="PART_Popup" AllowsTransparency="true" IsOpen="{Binding Path=IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}" Placement="Bottom" PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}" Grid.ColumnSpan="2" Width="{Binding ActualWidth,RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Grid}}">
<Border Name="DropDownBorder" Width="Auto" Height="Auto" BorderThickness="1,0,1,1" CornerRadius="0,0,4,4" BorderBrush="#FFbbbbbb">
<Border.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="White" Offset="0" />
<GradientStop Color="#FFE9E9E9" Offset="1" />
</LinearGradientBrush>
</Border.Background>
<ScrollViewer CanContentScroll="true">
<ItemsPresenter />
</ScrollViewer>
</Border>
</Popup>
<ToggleButton Style="{StaticResource cmbToggle}" Grid.ColumnSpan="2" IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"/>
<ContentPresenter HorizontalAlignment="Left" Margin="5,0,0,0" VerticalAlignment="Center" IsHitTestVisible="false" Content="{TemplateBinding SelectionBoxItem}" ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="cmbToggle" TargetType="{x:Type ToggleButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border Name="cmbBorder" CornerRadius="3" BorderBrush="#FFaaaaaa" BorderThickness="1.5">
<Border.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="White" Offset="0" />
<GradientStop Color="#FFE9E9E9" Offset="1" />
</LinearGradientBrush>
</Border.Background>
<Border BorderBrush="#FFaaaaaa" BorderThickness="1,0,0,0" Width="20" HorizontalAlignment="Right">
<Polygon Name="pol" Fill="#FF787878" Points="4,9 8,14 12,9" Stroke="#FF787878" StrokeThickness="0" Margin="1 1 0 0">
</Polygon>
</Border>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="CornerRadius" TargetName="cmbBorder" Value="4,4,0,0"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
So My idea is to change width of Popup dynamically(Combobox width - togglebutton width = popup width).I have written style in App.xaml
How to do this, Please help me. Thanks in advance.
Ok so in your ToggleButton Style we can see the Border holding Polygon arrow is 20 in Width. That's the Width to be removed from the Popup
Thus we can do something like:
Firstly add 2 Column's to the Grid in ComboBox ControlTemplate
<ControlTemplate TargetType="{x:Type ComboBox}">
<Grid>
<!-- New Bit -->
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<!-- End of New Bit -->
<Popup x:Name="PART_Popup"
Grid.ColumnSpan="2"
...
and then update the Width of Popup to
<Popup x:Name="PART_Popup"
Grid.ColumnSpan="2"
Width="{Binding Path=ColumnDefinitions[0].ActualWidth,
RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType=Grid}}"
...
Your Style already has ColumnSpan mentioned on appropriate controls, so nothing else is needed. This should give you the output your looking for.
you can directly use
<ComboBox.Resources>
<Style TargetType="{x:Type Popup}">
<Setter Property="Width" Value="110"/>
</Style>
</ComboBox.Resources>
Using Dhaval Patel's solution bound to a view model property did the trick.
I calculate the max width using FormattedText when the collection changes and it bind it below.
<ComboBox.Resources>
<Style TargetType="{x:Type Popup}">
<Setter Property="Width" Value="{Binding MaxWidthOfMyCollection"/>
</Style>
</ComboBox.Resources>
I have a Stackpanel inside of a TabItem that is part of a TabControl. As things get added to the StackPanel, I have a custom vertical ScrollBar appear. Currently its appearing inside the TabItem control "on top of" the stack panel. I want to move the scroll bar's location to outside of the TabControl altogether. I've tried to do some things with margin, but as the ScrollBar gets pushed outside the edge of the TabControl, it just gets clipped, and no amount of me messing with zindex has resulted in any success. Any help would be appreciative. - Leif
<TabItem Name="tabItem1" Background="{x:Null}" BorderBrush="#FF48D6EE" IsSelected="True">
<TabItem.Template>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid>
<Border Name="Tab1" Margin="0,0,0,0" BorderBrush="#FF002648" BorderThickness="1,0,1,1" CornerRadius="0,0,3,3">
<Border.Effect>
<DropShadowEffect ShadowDepth="0" Color="#FF3Ed3F4" Opacity=".5" BlurRadius="2"/>
</Border.Effect>
</Border>
<HeaderedContentControl Name="TabHeaderText"
TextBlock.FontFamily="Aharoni"
TextBlock.FontWeight="Bold"
TextBlock.Foreground="#FF214c6d"
TextBlock.FontSize="18"
Header="Tab1"
Margin="10,1,10,0"
VerticalAlignment="Center"
HorizontalAlignment="Center"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Tab1" Property="Background">
<Setter.Value>
<LinearGradientBrush StartPoint=".5,0" EndPoint=".5,1">
<GradientStop Color="#FF000a13" Offset="0" />
<GradientStop Color="#FF06335c" Offset="0.5" />
<GradientStop Color="#FF33bbdb" Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter TargetName="Tab1" Property="Effect">
<Setter.Value>
<DropShadowEffect ShadowDepth="0" Color="#FF3ccbee" Opacity="1" BlurRadius="5"/>
</Setter.Value>
</Setter>
<Setter TargetName="Tab1" Property="BorderBrush" Value="#FF48d6ed"/>
<Setter TargetName="Tab1" Property="BorderThickness" Value="1,0,1,1" />
<Setter TargetName="Tab1" Property="Header">
<Setter.Value>
<custom:OutlinedText FontSize="18"
FontFamily="Aharoni"
FontWeight="ExtraBold"
Fill="Black"
Stroke="#ff3bb1db"
StrokeThickness=".75"
Text="Tab1"/>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</TabItem.Template>
<ScrollViewer HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto"
Template="{StaticResource ScrollViewerControlTemplate}">
<StackPanel Name="panelTab1" HorizontalAlignment="Left" VerticalAlignment="Top"/>
</ScrollViewer>
</TabItem>
We ran into a similar issue. What we discovered is that WPF does not draw things with negative margins, when they are clipped. Clipping comes into play when one of the elements that contains the TabItem control has a MinHeight set, and the window shrinks below the MinHeight. By default the scroll bar uses a negative margin for the PART_VerticalScrollBar.
The solution is to make sure that you do not have MinHeight set on any of the containers that may contain your TabItem. If you need to use MinHeight, set it on the top level view.
The Snoop tool is very helpful for debugging WPF layout issues.
http://snoopwpf.codeplex.com/
I want to create a custom WPF dropdown menu, so I created a User control which contains a ToggleButton and a Popup control. The popup appears when I click on the button.
Now I want to add a mouse hover effect on the menu items in the popup: but the LinearGradientBrush is not working with alpha channels:
<UserControl.Resources>
...
<Style x:Key="SubMenuItemStyle" TargetType="{x:Type MenuItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="MenuItem">
<Grid Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" ClipToBounds="True">
<Rectangle x:Name="rectangle" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Stroke="{TemplateBinding BorderBrush}" StrokeThickness="{TemplateBinding BorderThickness}"
Fill="{TemplateBinding Background}" />
<StackPanel>
<TextBlock x:Name="text" Text="{TemplateBinding Header}" Foreground="{TemplateBinding Foreground}" />
</StackPanel>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Stroke" TargetName="rectangle" Value="#30000000"/>
<Setter Property="Fill" TargetName="rectangle">
<Setter.Value>
<LinearGradientBrush EndPoint="0,0" StartPoint="1,1">
<GradientStop Color="#10000000" Offset="0"/>
<GradientStop Color="#10FFFFFF" Offset="1"/>
<!-- Not works... -->
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" TargetName="text" Value="#FF9A9A9A"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid>
<Controls:ToggleImageButton Style="{DynamicResource ArrowMenuStyle}" x:Name="imageButton" Height="21" />
<Popup x:Name="popup" PlacementTarget="{Binding ElementName=imageButton}" Placement="Bottom" StaysOpen="False" IsOpen="{Binding ElementName=imageButton, Path=IsChecked}">
<ItemsControl ItemsSource="{Binding MenuCommands}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<MenuItem Header="{Binding Name}" Command="{Binding Command}" Background="{Binding ElementName=popupMenuControl, Path=MenuBackground}" Foreground="{Binding ElementName=popupMenuControl, Path=MenuForeground}" Click="MenuItem_Click" Style="{StaticResource SubMenuItemStyle}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Popup>
</Grid>
When I set the GradientBrush to this, everything works fine:
<LinearGradientBrush EndPoint="0,0" StartPoint="1,1">
<GradientStop Color="Green" Offset="0"/>
<GradientStop Color="Yellow" Offset="1"/>
</LinearGradientBrush>
But it seems the Alpha channel breaks the whole thing, and what I see is a black rectangle.
...Any idea?
If I put the MenuItems inside a Menu container, the Menu overrides my styles...
Thanks in advance!
have you set AllowsTransparency to true?
I'd like to make a TextBox with a Button inside, something like a DatePicker, but not exactly. Or can it be a ComboBox inside the TextBox, so you can switch the mode of the TextBox.
Can you help me?
If you want something like a combobox or a date time picker you should create a new control, inside this new control place a text box and a button side by side inside a frame that looks like the frame of a textbox - then restyle the textbox so it doesn't have a frame.
putting a button inside a rich edit is great if you want to put a button inside a "document" but not a good substitute for a combobox.
See the ComboBox control template MSDN
I created a textbox control and added this
It seems to work, but not the ideal situation cos it recreates another textbox.
<TextBox.Template>
<ControlTemplate>
<Grid>
<Grid.ColumnDefinitions></Grid.ColumnDefinitions>
<TextBox Grid.Column="0"></TextBox>
<Button HorizontalAlignment="Right" Width="25" Grid.Column="1">
</Button>
</Grid>
</ControlTemplate>
</TextBox.Template>
Simple solution
You can fake the fact that the button is in the TextBox by putting the Button over the TextBox. Don’t forget to put padding on your TextBox to avoid text going behind the Button.
Code example with StackPanel :
<StackPanel Orientation="Horizontal">
<TextBox Width="200" Padding="0,0,30,0" Height="30" FontSize="16"/>
<Button Width="20" Height="20" Margin="-30,0,0,0"/>
</StackPanel>
Code example with Grid :
<Grid>
<TextBox Width="200" Padding="0,0,30,0" Height="30" FontSize="16"/>
<Button Width="20" Height="20" HorizontalAlignment="Right" Margin="0,0,5,0"/>
</Grid>
Result :
You may find this link helps: http://msdn.microsoft.com/en-us/library/ms752068(VS.85).aspx.
"The ControlTemplate for a TextBox must contain exactly one element that is tagged as the content host element; this element will be used to render the contents of the TextBox. To tag an element as the content host, assign it the special name PART_ContentHost. The content host element must be either a ScrollViewer or an AdornerDecorator. The content host element may not host any child elements."
You can use RichTextBox instead of textbox and it support flowdocument in which you can place the button in it.
You can also use a Label and change its template to include a Button in it. To have a good overview of differences between Label and TextBlock see this post.
The correct method of doing this is to use a control template on the textbox. Something like below. I used this inside a class that inherits from textbox and called it ButtonBox. I then inherit others from this such as DateBox, DateTimeBox, SqlServerConnectBox etc.
xmlns:mwt="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"
<TextBox.Template>
<ControlTemplate TargetType="{x:Type TextBoxBase}">
<mwt:ListBoxChrome
Background="{TemplateBinding Panel.Background}"
BorderBrush="{TemplateBinding Border.BorderBrush}"
BorderThickness="{TemplateBinding Border.BorderThickness}"
RenderMouseOver="{TemplateBinding UIElement.IsMouseOver}"
RenderFocused="{TemplateBinding UIElement.IsKeyboardFocusWithin}"
Name="Bd"
SnapsToDevicePixels="True">
<DockPanel>
<Button DockPanel.Dock="Right" Name="myButton" Padding="3,0" Click="myButton_Click">...</Button>
<ScrollViewer Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}"></ScrollViewer>
</DockPanel>
</mwt:ListBoxChrome>
<ControlTemplate.Triggers>
<Trigger Property="UIElement.IsEnabled">
<Setter Property="Panel.Background" TargetName="Bd">
<Setter.Value>
<DynamicResource ResourceKey="{x:Static SystemColors.ControlBrushKey}" />
</Setter.Value>
</Setter>
<Setter Property="TextElement.Foreground">
<Setter.Value>
<DynamicResource ResourceKey="{x:Static SystemColors.GrayTextBrushKey}" />
</Setter.Value>
</Setter>
<Trigger.Value>
<s:Boolean>False</s:Boolean>
</Trigger.Value>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</TextBox.Template>
Edit: I've change the method I was using so that it inherits from control and not textbox. This works well because the control just consists of a border, a textbox and a button. I was getting focus issues with the above solution. This is new template, I have called my control a ButtonBox
<Style TargetType="{x:Type local:ButtonBox}">
<Setter Property="Border.BorderThickness" Value="1"></Setter>
<Setter Property="Border.BorderBrush">
<Setter.Value>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,20" MappingMode="Absolute">
<LinearGradientBrush.GradientStops>
<GradientStop Color="#FFABADB3" Offset="0.05" />
<GradientStop Color="#FFE2E3EA" Offset="0.07" />
<GradientStop Color="#FFE3E9EF" Offset="1" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:ButtonBox}">
<mwt:ListBoxChrome
Background="{TemplateBinding Panel.Background}"
BorderThickness="{TemplateBinding Border.BorderThickness}"
BorderBrush="{TemplateBinding Border.BorderBrush}"
RenderMouseOver="{TemplateBinding UIElement.IsMouseOver}"
RenderFocused="{TemplateBinding UIElement.IsKeyboardFocusWithin}"
Name="Bd"
SnapsToDevicePixels="True">
<DockPanel>
<Button
DockPanel.Dock="Right"
Name="PART_Button"
Height="0"
Style="{x:Null}"
Margin="0"
Padding="3,0"
Content="{TemplateBinding local:ButtonBox.ButtonContent}"
IsTabStop="False">
</Button>
<TextBox
BorderBrush="{x:Null}"
BorderThickness="0"
Margin="0"
Name="PART_ContentHost"
IsReadOnly="{TemplateBinding TextBox.IsReadOnly}"
Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay, Path=Text}">
</TextBox>
<!-- ScrollViewer Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" Margin="1"></ScrollViewer -->
</DockPanel>
</mwt:ListBoxChrome>
<ControlTemplate.Triggers>
<Trigger Property="UIElement.IsEnabled">
<Setter Property="Panel.Background" TargetName="Bd">
<Setter.Value>
<DynamicResource ResourceKey="{x:Static SystemColors.ControlBrushKey}" />
</Setter.Value>
</Setter>
<Setter Property="TextElement.Foreground">
<Setter.Value>
<DynamicResource ResourceKey="{x:Static SystemColors.GrayTextBrushKey}" />
</Setter.Value>
</Setter>
<Trigger.Value>
<s:Boolean>False</s:Boolean>
</Trigger.Value>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="IsTabStop" Value="False"></Setter>
</Style>
Just use Grid.Column same like below code
<TextBox x:Name="txtUrl" Grid.Column="1" Margin="2,2,0,2" VerticalAlignment="Center" Padding="2" PreviewKeyDown="txtUrl_PreviewKeyDown" GotFocus="txtUrl_GotFocus" PreviewMouseDown="txtUrl_PreviewMouseDown">
</TextBox>
<eo:BareButton x:Name="btnAddFavorite" Grid.Column=" 1" HorizontalAlignment="Right" Style="{StaticResource WindowButtonStyle }" Margin="2" >
<eo:BareButton.Template>
<ControlTemplate TargetType="{x:Type eo:BareButton}">
<Border x:Name="PART_Border" Width="22" Height="22" Background="Transparent" VerticalAlignment="Center" Margin="2,0,0,0" CornerRadius="2">
<Path
HorizontalAlignment="Center"
VerticalAlignment="Center"
Fill="Yellow"
Data="M 2,9 L 8,8 10,2 13,8 19,9 15,13 16,19 10,15 5,19 6,13 2,9"
SnapsToDevicePixels="false"
Stroke="{Binding Foreground, RelativeSource={RelativeSource AncestorType={x:Type eo:BareButton}, Mode=FindAncestor}}"
StrokeThickness="1" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="PART_Border" Property="BorderBrush" Value="#666"/>
<Setter TargetName="PART_Border" Property="BorderThickness" Value="1"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</eo:BareButton.Template>
</eo:BareButton>
You may use a grid to accomplish this task. The following is how I created a button which appears at the right bottom of a TextBox:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBox VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Grid.Row="0" />
<Button Content="Copy" Width="40" Height="40" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="10" Grid.Row="0" />
</Grid>