Apply DropShadowEffect to WPF Textbox text - c#

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>

Related

Auto scrolling on TextBox ControlTemplate

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.

Bind color of SolidColorBrush to background color of Button

I created a custom rounded button with following code But the color button doesn't follow the Background property of button so i have to create new style for each color of button.
How can i bind SolidColorBrush Color to Button Background color ?
<Style x:Key="RoundedButton" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Rectangle RadiusX="6" RadiusY="6">
<Rectangle.Fill>
<SolidColorBrush Color="BUTTON BACKGROUND"/>
</Rectangle.Fill>
</Rectangle>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The Button's Background is already a Brush. No need to create another one:
<ControlTemplate TargetType="Button">
<Grid>
<Rectangle RadiusX="6" RadiusY="6" Fill="{TemplateBinding Background}"/>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</ControlTemplate>
You will probably have to use a one way DataBinding

Cannot see controls in WPF window after applying style/template to Window

I have a custom template for my application Windows that I have built. It's in App.xaml
<Application.Resources>
<ResourceDictionary>
<Style x:Key="XWindow" TargetType="{x:Type Window}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate >
<Border BorderThickness="3">
<Border.Effect>
<DropShadowEffect BlurRadius="5" Direction="270" RenderingBias="Quality" ShadowDepth="0.5" Opacity="0.8" Color="#FF00B9FF"/>
</Border.Effect>
<Grid Background="White">
<local:ControlButtons Height="38" VerticalAlignment="Top" HorizontalAlignment="Right"/>
<Border BorderBrush="#99007CF7" BorderThickness="1"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
</Application.Resources>
In my MainWindow.xaml I have applied this style like this (and it works) : <Window [...] Style="{DynamicResource XWindow }"
So the style is applied to the window. But when I put a control in the Window, I cannot see it or even select it. It's in the XAML code but even when I debug it's not on the Window.. Anyone has a clue ?
There's a screenshot :
XAML Problem
This is what it should normally do when I add a simple button : XAML Norrmal
As pointed out by #Clemens you have forgotten to add a ContentPresenter to your ControlTemplate. This is where the actual content of the window will be displayed.
You should also remember to put the ContentPresenter in an AdornedDecorator:
<Style x:Key="XWindow" TargetType="{x:Type Window}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Window}">
<Border BorderThickness="3">
<Border.Effect>
<DropShadowEffect BlurRadius="5" Direction="270" RenderingBias="Quality" ShadowDepth="0.5" Opacity="0.8" Color="#FF00B9FF"/>
</Border.Effect>
<Grid Background="White">
<local:ControlButtons Height="38" VerticalAlignment="Top" HorizontalAlignment="Right"/>
<Border BorderBrush="#99007CF7" BorderThickness="1">
<AdornerDecorator>
<ContentPresenter/>
</AdornerDecorator>
</Border>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The AdornedDecorator specifies the position of the AdornerLayer in the visual tree as stated on MSDN here: http://msdn.microsoft.com/en-us/library/system.windows.documents.adornerdecorator.aspx. You will for example need one if you intend to dipslay any validation errors in your window as validation errors are displayed on the adorner layer.
Edit: You should also set the TargetType property of the ControlTemplate:
<ControlTemplate TargetType="{x:Type Window}">

Change Image when mouse is over with Binding c# WPF

I am doing a program in WPF that has different rectangles disposed inside a grid. They all have an imagesource binding that makes the image change dynamically throughout the program. It's similar to the 2048. The thing is that now I want to make this rectangle change its imagesource when the mouse is over it. Like I already did an imagesource binding I cant figure out how to do it.
<ListBox Grid.Row="1" ItemsSource="{Binding Tiles}">
<ListBox.ItemTemplate>
<DataTemplate>
<Border Background="{Binding Converter={StaticResource BackgroundColor2048Converter}}" Width="106.25px" Height="106.25px" CornerRadius="3" BorderThickness="1" VerticalAlignment="Stretch" Focusable="False" HorizontalAlignment="Stretch" Margin="7">
<Rectangle Width="104.25px" Height="104.25px" MouseEnter="Rectangle_MouseEnter" MouseLeave="Rectangle_MouseLeave" >
<Rectangle.Fill>
<ImageBrush ImageSource="{Binding Converter={StaticResource ImageBackgroundColor2048Converter}, Mode=OneWay}"/>
</Rectangle.Fill>
</Rectangle>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
That's the xaml code regarding the rectangle. The imagesource converter works and is used to change the image during the game. But now I want to change that image too when the mouseenter event triggers. And thats where I am completely lost to, on how to do it.
You do this through a trigger:
<Rectangle Width="104.25px" Height="104.25px" MouseEnter="Rectangle_MouseEnter" MouseLeave="Rectangle_MouseLeave" >
<Rectangle.Style>
<Style TargetType="{x:Type Rectangle}">
<Setter Property="Fill" >
<Setter.Value>
<ImageBrush ImageSource="{Binding Converter={StaticResource ImageBackgroundColor2048Converter}, Mode=OneWay}"/>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Rectangle.IsMouseOver" Value="True">
<Setter Property="Fill" >
<Setter.Value>
<!-- Whatever you want here -->
<ImageBrush ImageSource="{Binding MouseOverImageUri}" />
</Setter.Value>
</Setter>
</Trigger>
</Style>
</Rectangle.Style>
</Rectangle>
Note that you have to set the default value through a style. The reason for this is that triggers override styles, but directly applied attributes override triggers. In this case, you want the trigger to win.

WPF Custom Control- Generic.xaml root element not supported by visual designer

I am trying to customise the Extended WPF Toolkit's RichTextBoxFormatBar tool as I want to take away some out of the box functionality.
I have created a Custom Control and copied the original tool source code into Themes\Generic.xaml
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Xceed.Wpf.Toolkit;assembly=Xceed.Wpf.Toolkit"
xmlns:conv="clr-namespace:Xceed.Wpf.Toolkit.Core.Converters;assembly=Xceed.Wpf.Toolkit"
xmlns:MyNamespace="clr-namespace:IsesTextEditor">
<conv:ColorToSolidColorBrushConverter x:Key="ColorToSolidColorBrushConverter" />
<ControlTemplate TargetType="{x:Type MyNamespace:IsesFormatBar}" x:Key="IsesFormatTemplate">
<Border Background="Transparent"
Cursor="Hand"
ToolTip="Click to Drag">
<StackPanel VerticalAlignment="Center"
Width="75">
<Line SnapsToDevicePixels="True"
Stretch="Fill"
StrokeDashArray="1,2"
StrokeThickness="1"
X1="0"
X2="1"
Margin=".5">
<Line.Stroke>
<SolidColorBrush Color="Gray" />
</Line.Stroke>
</Line>
<Line SnapsToDevicePixels="True"
Stretch="Fill"
StrokeDashArray="1,2"
StrokeThickness="1"
X1="0"
X2="1"
Margin=".5">
<Line.Stroke>
<SolidColorBrush Color="Gray" />
</Line.Stroke>
</Line>
<Line SnapsToDevicePixels="True"
Stretch="Fill"
StrokeDashArray="1,2"
StrokeThickness="1"
X1="0"
X2="1"
Margin=".5">
<Line.Stroke>
<SolidColorBrush Color="Gray" />
</Line.Stroke>
</Line>
</StackPanel>
</Border>
</ControlTemplate>
design blah blah design
</StackPanel>
</StackPanel>
</Grid>
</Border>
</ControlTemplate>
<!-- =================================================================== -->
<!-- Style -->
<!-- =================================================================== -->
<Style TargetType="{x:Type MyNamespace:IsesFormatBar}">
<Setter Property="Template"
Value="{StaticResource richTextBoxFormatBarTemplate}" />
<Setter Property="Effect">
<Setter.Value>
<DropShadowEffect BlurRadius="5"
Opacity=".25" />
</Setter.Value>
</Setter>
<Setter Property="Background"
Value="Transparent" />
<Setter Property="IsTabStop"
Value="false" />
</Style>
Sorry, lot of Xaml!
I have Ises.FormatBar.cs which holds all my code behind/logic and inherits from Control.
When I try to view the Designer for Generic.xaml I get no designer and the message 'Intentionally Left Blank. The document root element is not supported by the visual designer.'
Probably an issue with my xaml code not being bound properly to Ises.FormatBar.cs?
When I try to view the Designer for Generic.xaml I get no designer and
the message 'Intentionally Left Blank.
This is fine. It's because you are trying to view a ResourceDictionary in a designer.
Is that the only issue?
I would also make a guess that when you use this custom control into some other user control, you are not getting to see the expected view.
Ideally, you shouldn't be including "x:Key="IsesFormatTemplate" in your custom control style. So that it get's applied to all usages without having to include the style explicitly. Either remove the key, or include Style="{StaticResource IsesFormateTemplate}" in all the usages.

Categories