Stuck on button template with texbox - wpf

I have a button template shown bellow, in this case when the text is entered the button stays the same size, and it works ok. However I want just a border, so when I try to add that ellipse inside the thumb to get the border, and try typing text in the textbox, when the text becomes larger than the button suddenly it covers the button with a white background, i don't know why this is happening, any help would be appreciated.
<Window.Resources>
<Style TargetType="{x:Type Thumb}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Thumb">
<Ellipse Fill="{TemplateBinding Background}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Thumb x:Name="outerThumbResize" Cursor="SizeNESW" Background="Red" Height="50" Width="50"/>
<!--<Ellipse x:Name="innerCircle" Fill="White" RenderTransformOrigin=".5,.5">
<Ellipse.RenderTransform>
<ScaleTransform ScaleX=".8" ScaleY=".8"/>
</Ellipse.RenderTransform>
</Ellipse>-->
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBox x:Name="textBox" Background="Transparent" BorderThickness="0" Visibility="Collapsed" TextAlignment="Center" PreviewKeyUp="textBox_PreviewKeyUp" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<Thumb x:Name="innerThumb" Background="Transparent" DragDelta="nodeThumb_DragDelta" RenderTransformOrigin=".5,.5">
<Thumb.RenderTransform>
<ScaleTransform ScaleX=".9" ScaleY=".9"/>
</Thumb.RenderTransform>
</Thumb>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>

i solved it using the stroke thickness of the ellipse in the template.

Related

XAML - Cannot add border thickness to button when style is applied

I am trying to add a border thickness to my first navigation button. Normally, you can easily add a BorderThickness to a button but when I add my own style it hides the BorderThickness and BorderBrush. I added a BorderThickness to the style (0,0,0,1) but am not able to have a border thickness of (0,1,0,0) to the first initial button. Any ideas?
<UserControl.Resources>
<Style x:Key="navButtStyle" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
<Border BorderThickness="0,0,0,1" BorderBrush="Black"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Button Style="{StaticResource navButtStyle}"
x:Name="navButton1"
Grid.Row="1"
Content="TR"
Background="#33333D"
FontFamily="Roboto"
FontSize="65"
FontWeight="Bold"
Foreground="White"
BorderBrush="Black"
BorderThickness="0,1,0,0"
HorizontalContentAlignment="Center"
ToolTip="navButton0"
Click="navButton1_Click"
/>
<Button Style="{StaticResource navButtStyle}" x:Name="navButton2" Grid.Row="2" Background="#33333D" ToolTip="navButton2">
<Grid>
<TextBlock Text="󰂯" Padding="30,30,0,0" FontSize="56" FontFamily="Material Design Icons Desktop" Foreground="White"/>
<TextBlock Text="󰖩" Padding="0,0,30,30" FontSize="56" FontFamily="Material Design Icons Desktop" Foreground="White"/>
</Grid>
</Button>
<Button Style="{StaticResource navButtStyle}" x:Name="navButton3" Grid.Row="3" Content="SL" Background="#33333D" FontFamily="Roboto" FontSize="65" FontWeight="Bold" Foreground="White" HorizontalContentAlignment="Center" ToolTip="navButton3" />
Navigation Buttons
property value hardcoded in Template cannot be easily changed from outside. use TemplateBindings instead:
<Style x:Key="navButtStyle" TargetType="Button">
<Setter Property="BorderThickness" Value="0,0,0,1"/>
<Setter Property="BorderBrush" Value="Black"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
<Border BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

WPF Progressbar style text

I have a style for a progressbar that shows some text only on the PART_Indicator section:
<Style x:Key="{x:Type ProgressBar}" TargetType="{x:Type ProgressBar}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ProgressBar}">
<Grid MinHeight="14" MinWidth="200">
<Border Name="PART_Track" CornerRadius="15" Background="{StaticResource PressedBrush}" BorderBrush="{StaticResource SolidBorderBrush}" BorderThickness="1" />
<Border Name="PART_Indicator" CornerRadius="15" Background="#CEAC2D" BorderBrush="#CEAC2D" BorderThickness="1" HorizontalAlignment="Left" >
<Viewbox>
<TextBlock TextAlignment="Center" Background="Transparent" FontFamily="Times" Foreground="Black" Margin="2,2,2,2"
Text="{Binding ProgressText}"/>
</Viewbox>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I have a few bars and each one should show a different kind of text (50%, 2/8, etc..) and that of course is handled by the VM.
My question is how to use this style for all the bars but differentiate only that textblock text. I presume the binding is not correct .. I probably need a TemplateBinding, but to what property?

WPF Window Chrome styling

I'm using WindowChrome class for solving problem with different icons in task bar and app header. Here is my window.style example:
<Window.Style>
<Style TargetType="{x:Type local:MainWindow}">
<Setter Property="shell:WindowChrome.WindowChrome">
<Setter.Value>
<shell:WindowChrome GlassFrameThickness="-1"
ResizeBorderThickness="4"
UseAeroCaptionButtons="True"/>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:MainWindow}">
<Grid>
<!-- This is the ContentPresenter that displays the window content. -->
<Border Margin="1 30 1 1" Background="White"
>
<ContentPresenter Content="{TemplateBinding Content}" />
</Border>
<!-- Window Title -->
<Image Margin="5" VerticalAlignment="Top" HorizontalAlignment="Left" Width="16" Height="16" Source="some.ico"></Image>
<TextBlock Margin="25 5 0 0" VerticalAlignment="Top" TextAlignment="Left"
Text="{Binding RelativeSource=
{RelativeSource TemplatedParent}, Path=Title}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Style>
When not maximized - my window looks as I want.
But when maximized(by double click/maximize button click or dock to the top) the header background is black, I can't see any buttons and my icon is out of the screen bounds. :(
Any suggestions? What i'm doing wrong in my style?

Reading Content property of a Button into a ConrtolTemplate in a style

I have a style for a button with a ControlTemplate something like this
<Style x:Key="ButtonStyle"
BasedOn="{x:Null}"
TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<Rectangle x:Name="rectangle"
Fill="#FF04822A"
Stroke="{x:Null}" />
<TextBlock HorizontalAlignment="Center"
VerticalAlignment="Center"
FontWeight="Heavy"
Foreground="Black"
x:Name="btnText"
TextAlignment="Center" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Button Grid.Row="3"
Grid.Column="5"
Margin="4,0,4,0"
Command="{Binding ResetCommand}"
Content ="Reset Cells"
Style="{StaticResource ButtonStyle}" />
I want the TextBlock to read from the button Content every time its updated.
Add a template binding to the TextBlock:
Text="{TemplateBinding Content}"
You might just want to use a ContentPresenter instead though (as TextBlocks usually only display text).

How to make a TextBox with a Button inside in WPF?

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>

Resources