Auto scrolling on TextBox ControlTemplate - c#

I'm using the TextBox below, which in order to apply a DropShadowEffect on its text, uses a ControlTemplate. I managed to get the TextWrapping to work, but once the TextBox fills up, it's content goes out of view. How do I replicate the Auto scrolling to the bottom feature of a native TextBox?
<TextBox TextWrapping="Wrap"
Foreground="LimeGreen"
Background="Black"
Margin="10,40,10,40"
FontSize="40"
HorizontalAlignment="Stretch"
x:Name="Inp"
FontFamily="Courier New"
CaretBrush='LimeGreen'>
<TextBox.Resources>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Grid x:Name="RootElement">
<ScrollViewer>
<ContentPresenter Content="{TemplateBinding Text}">
<ContentPresenter.Effect>
<DropShadowEffect ShadowDepth="4"
Direction="330"
Color="LimeGreen"
Opacity="1"
BlurRadius="5" />
</ContentPresenter.Effect>
<ContentPresenter.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property='TextWrapping'
Value='Wrap' />
</Style>
</ContentPresenter.Resources>
</ContentPresenter>
</ScrollViewer>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</TextBox.Resources>
</TextBox>

This solution is a bit different that what you might expect. I think using the ContentPresenter is the wrong way because in the end you still want the functionality of the TextBox. So my solution focuses on getting rid of the border and focus indicator that mess up the drop shadow effect:
<TextBox x:Name="Inp"
Height="100"
HorizontalAlignment="Stretch"
Background="Transparent"
BorderBrush="Transparent"
BorderThickness="0"
CaretBrush="LimeGreen"
FontFamily="Courier New"
FontSize="40"
Foreground="LimeGreen"
TextWrapping="Wrap">
<TextBox.Effect>
<DropShadowEffect BlurRadius="5"
Direction="330"
Opacity="1"
ShadowDepth="4"
Color="LimeGreen" />
</TextBox.Effect>
<TextBox.FocusVisualStyle>
<Style>
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate/>
</Setter.Value>
</Setter>
</Style>
</TextBox.FocusVisualStyle>
</TextBox>
I set the Background, BorderBrush to be transparent (=> no shadow). I removed the ContentPresenter; it's a 'regular textbox now. And to remove the focus border I set the FocusVisualStyle to an empty Template.

Related

Using WindowChrome Class to set title bar background

I am wanting to just set the title bar and border of a WPF window but the title background property doesn't look to be exposed in the class.
I want to leave all default Window behavior and just set the color property of Title Bar and Border
What is the correct property to set?
I am refrencing: https://learn.microsoft.com/en-us/dotnet/api/system.windows.shell.windowchrome?view=netframework-4.7.2
<ResourceDictionary>
<Style x:Key="CustomWindowStyle" TargetType="{x:Type Window}">
<Setter Property="WindowChrome.WindowChrome">
<Setter.Value>
<WindowChrome/>
</Setter.Value>
</Setter>
<Setter Property="??" Value="Blue"/>
</Style>
</ResourceDictionary>
The only property I see is the Title Property and setting its color has no effect
So I resolved this and it was more involved then I had originally thought. Since the title bar is in the non-client area when editing it I would lose the visibility of the corner buttons.
In the end I had to reconstruct the title bar and create a class to implement the buttons to get the look I desired.
This will give you a window with a border and the title bar will also have a color. You need to implement the corner buttons though.
xmlns:shell="http://schemas.microsoft.com/netfx/2009/xaml/presentation"
<Style x:Key="StandardStyle" TargetType="{x:Type Window}">
<Setter Property="shell:WindowChrome.WindowChrome">
<Setter.Value>
<shell:WindowChrome
/>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Window}" >
<Grid>
<!--Title Panel-->
<DockPanel LastChildFill="True">
<Border Background="Blue" DockPanel.Dock="Top"
Height="{x:Static SystemParameters.CaptionHeight}" x:Name="titlebar">
<Grid>
<!--Title text only-->
<TextBlock Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Title}"
VerticalAlignment="Top" HorizontalAlignment="Center" Background="Transparent" />
<usercontrols:CornerButtons HorizontalAlignment="Right"/>
</Grid>
</Border>
<!--Provides the actual content control-->
<Border Margin="0,0,0,0" >
<AdornerDecorator>
<ContentPresenter Content="{TemplateBinding Content}"/>
</AdornerDecorator>
</Border>
</DockPanel>
<!--Provides the actual window border-->
<Border
Margin="0,0,0,0"
Background="White"
Grid.ZIndex="-1"
BorderThickness="2,2,2,2" BorderBrush="Blue"
>
</Border>
<!--This is the top left system button-->
<!--<Button
Margin="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(shell:WindowChrome.WindowChrome).ResizeBorderThickness}"
Padding="1"
HorizontalAlignment="Left"
VerticalAlignment="Top"
shell:WindowChrome.IsHitTestVisibleInChrome="True"
Command="{x:Static shell:SystemCommands.ShowSystemMenuCommand}"
CommandParameter="{Binding ElementName=CalcWindow}">
<Image
Width="16"
Height="16"
shell:WindowChrome.IsHitTestVisibleInChrome="True"
Source="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Icon}" />
</Button>-->
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Apply DropShadowEffect to WPF Textbox text

How can I apply the DropShadowEffect on the content of a TextBox, as opposed to around the TextBox itself? I'd like the text to have the same effect as if I applied DropShadowEffect to a TextBlock.
<TextBox>
<TextBox.Effect>
<DropShadowEffect ShadowDepth="4"
Direction="330"
Color="Black"
Opacity="0.5"
BlurRadius="4"/>
</TextBox.Effect>
</TextBox>
^This creates shadow around the entire box.
<TextBlock>
<TextBlock.Effect>
<DropShadowEffect ShadowDepth="4"
Direction="330"
Color="Black"
Opacity="0.5"
BlurRadius="4"/>
</TextBlock.Effect>
</TextBlock>
^This is the desired look. (But for the TextBox text)
EDIT: Take home message is that shaders are applied to every rendered pixel of a control. If you want to apply it to only parts of it, either apply it on that level on that template, or don't render everything else.
Instead you might want to remove the Border, Background and Focus rectangle from the textbox so you still have the TextBox functionality:
<TextBox Background="Transparent"
BorderBrush="Transparent"
BorderThickness="0"
TextWrapping="Wrap">
<TextBox.Effect>
<DropShadowEffect ShadowDepth="4"
Direction="330"
Color="Black"
Opacity="0.5"
BlurRadius="4"
/>
</TextBox.Effect>
<TextBox.FocusVisualStyle>
<Style>
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate/>
</Setter.Value>
</Setter>
</Style>
</TextBox.FocusVisualStyle>
</TextBox>
By customizing the ControlTemplate of your TextBox, you can achive the desired effect:
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Grid x:Name="RootElement">
<!-- Use your effects on the ContentPresenter here. -->
<ContentPresenter Content="{TemplateBinding Padding}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>

Custom tooltip validation error WPF

I'm trying to create a custom tooltip. The problem is that I can not display the error text. This code works perfectly (a simple tooltip)
<Style TargetType="{x:Type TextBox}"
BasedOn="{StaticResource {x:Type TextBox}}">
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<Grid>
<Polygon Fill="Red"
Margin="0,2,2,0"
Points="10,10 10,0 0,0"
VerticalAlignment="Top"
HorizontalAlignment="Right"
ToolTip="{Binding ElementName=adorner, Path=AdornedElement.(Validation.Errors).CurrentItem.ErrorContent}">
</Polygon>
<AdornedElementPlaceholder x:Name="adorner" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
But this code, not work, not show the error
<Style TargetType="{x:Type TextBox}"
BasedOn="{StaticResource {x:Type TextBox}}">
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<Grid>
<Polygon Fill="Red"
Margin="0,2,2,0"
Points="10,10 10,0 0,0"
VerticalAlignment="Top"
HorizontalAlignment="Right">
<Polygon.ToolTip>
<ToolTip Content="{Binding ElementName=adorner, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}"
BorderThickness="1"
Foreground="White"
Background="Red" />
</Polygon.ToolTip>
</Polygon>
<AdornedElementPlaceholder x:Name="adorner" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
The Tooltip itself and the AdornedElementPlaceholder reside in different namescopes so binding using an ElementName won't work.
But you can set the Tag property of the Polygon to the ErrorContent and bind the Content property of the Tooltip to the Tag property of its PlacementTarget (which is the Polygon). This works:
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<Grid>
<Polygon Fill="Red"
Margin="0,2,2,0"
Points="10,10 10,0 0,0"
VerticalAlignment="Top"
HorizontalAlignment="Right"
Tag="{Binding ElementName=adorner, Path=AdornedElement.(Validation.Errors).CurrentItem.ErrorContent}">
<Polygon.ToolTip>
<ToolTip Content="{Binding PlacementTarget.Tag, RelativeSource={RelativeSource Self}}"
BorderThickness="1"
Foreground="White"
Background="Red" />
</Polygon.ToolTip>
</Polygon>
<AdornedElementPlaceholder x:Name="adorner" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The call to (Validation.Errors)[0] will be troublesome as you are referencing a particular object from a list that will update and change therefore breaking the binding.
The first example where you use (Validation.Errors).CurrentItem. is more suitable as it matches your first implementation which works.
I ran into issues with this a few years back, basically never use an index in a binding unless you are absolutely 100% sure it will not change.

Silverlight: Align button controls to right inside Datagrid cell

I have been trying this for a while. I am just stuck and can't get through it.
There are three controls in the datagrid cell.
1: A hyperlink Button
2: A clear button
3: A search button
What i need to do is to align the "clear" and "open button" align to the right of the column. The catch is the column is resizable.
I tried to give a fixed width to the hyperlink button it looks good but it gets messy when the column is resized.
The cell content has below style.
<Style TargetType="controls:HyperlinkClear">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="controls:HyperlinkClear">
<Border BorderThickness="0" Margin="2" BorderBrush="Transparent">
<Border.Resources>
<Style x:Name="buttonStyle"
TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid Width="12"
Height="12">
<TextBlock Margin="{TemplateBinding Margin}" Text="x"></TextBlock>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Border.Resources>
<controlsToolkit:DockPanel Background="Transparent">
<Button Margin="-2,0,0,0" controlsToolkit:DockPanel.Dock="Right" HorizontalAlignment="Right" x:Name="MainSearchButton" Style="{StaticResource ButtonStyle}" IsTabStop="False"
Visibility ="{Binding IsRemoveButtonEnabled,Converter={StaticResource BoolToVisibilityConverter},Mode=TwoWay}">
<Image Source="./open.png" Height="14" Width="16" VerticalAlignment="Center"/>
</Button>
<Button controlsToolkit:DockPanel.Dock="Right" Cursor="hand"
Margin="3,-2,0,0" Visibility ="{Binding IsRemoveButtonEnabled,Converter={StaticResource BoolToVisibilityConverter},Mode=TwoWay}"
x:Name="RemoveItemButton" HorizontalAlignment="Right"
Style="{StaticResource buttonStyle}" IsTabStop="false"/>
<HyperlinkButton x:Name="HyperlinkButton" Style="{StaticResource HyperlinkButtonStyle}" Content="{TemplateBinding Content}" />
</controlsToolkit:DockPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Currently it looks like this.
Expected
I found the solution. The solution is to set the cellcontent's horizontal alignment to "Stretch".
Override the BindCellContent Method of the column.
public override void BindCellContent(FrameworkElement cellContent, DataGridRow row)
{
var hyperlinkButton = (HyperlinkClear)cellContent;
hyperlinkButton.HorizontalAlignment = HorizontalAlignment.Stretch;
}

Stretching not applying in a WPF templated Button

I created a templated button in WPF :
<ControlTemplate TargetType="{x:Type Button}"
x:Key="BoutonGris">
<Button Foreground="White"
BorderBrush="Transparent"
HorizontalAlignment="Center"
VerticalAlignment="Center"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch">
<Button.Content>
<Border CornerRadius="3"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<ContentPresenter />
<Border.Style>
<Style TargetType="{x:Type Border}">
<Setter Property="Background"
Value="#58585a" />
<Style.Triggers>
<Trigger Property="IsMouseOver"
Value="True">
<Setter Property="Background"
Value="{DynamicResource DegradeCouleurTheme}" />
</Trigger>
</Style.Triggers>
</Style>
</Border.Style>
</Border>
</Button.Content>
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<ContentPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Button.Style>
</Button>
</ControlTemplate>
I use this button in my Window :
<Button x:Name="BtnRestoreDefault" Template="{DynamicResource BoutonGris}" Content="Rest. défaut" Height="27" Width="88" Click="Button_Click_RestoreDefault"/>
My problem is that the button don't appear to have the Height="27" and Width="88".
Here is my result in VS2012 :
The button has the good size, but the gray area don't. I have use the Stretch keywords on the Template but i don't find the mistake.
If i use Stretch for HorizontalAlignment, HorizontalContentAlignment, VerticalAlignment, and VerticalContentAlignment, the gray has the good size, but, the text content is in left/up ! I would like a center text.
Anyone have an idea please ?
Thanks a lot,
Best regards,
Nixeus
This should do the trick.
<ControlTemplate TargetType="{x:Type Button}" x:Key="BoutonGris">
<Button Foreground="White" BorderBrush="Transparent"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" >
<Button.Content>
<!-- A lot of your code -->
</Button.Content>
<!-- A lot of your code -->
</Button>
</ControlTemplate>
One question, why do you have a Button in your ControlTemplate for a Button? Usually, I would expect simple controls like Border etc here, because you want to reimplement the visual appearance.
Edit
One of the ContentPresenter should be declared like this.
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
I'm not sure which one. But you can try both. ;o)

Categories