TextPreview for Textbox - c#

Reworked Question to clarify my needs:
I want to add a preview Text to Textboxes when they're empty, just like some of you may know it from Xamarin.
I have found this answer on SO.
This is the Style from the Answer I linked above.
<TextBlock Grid.Row="5"
Grid.Column="1"
VerticalAlignment="Center"
Text="Username:">
</TextBlock>
<TextBox Grid.Row="5"
Grid.Column="3">
<TextBox.Style>
<Style TargetType="TextBox">
<Style.Resources>
<VisualBrush x:Key="CueBannerBrush" AlignmentX="Left" AlignmentY="Center" Stretch="None">
<VisualBrush.Visual>
<Label Content="Test" Foreground="LightGray" />
</VisualBrush.Visual>
</VisualBrush>
</Style.Resources>
<Style.Triggers>
<Trigger Property="Text" Value="{x:Static sys:String.Empty}">
<Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
</Trigger>
<Trigger Property="Text" Value="{x:Null}">
<Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter Property="Background" Value="White" />
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
I get the following result:
Since this is working nicely I want to apply it to every TextBox in that Window.
So my approach was to change this line:
<Label Content="Test" Foreground="LightGray" />
I thought maybe changing it to <Label Content="Test" Foreground="LightGray" /> would do the trick, but it is not working.
I guess it's something with the Tag Property and the Type of it (object instead of string).
Since the first approach is working like charm I don't really see why I should need a custom control for that...
So what I tried then is this:
<Window.Resources>
<Style TargetType="TextBox">
<Style.Resources>
<VisualBrush x:Key="CueBannerBrush" AlignmentX="Left" AlignmentY="Center" Stretch="None">
<VisualBrush.Visual>
<Label Content="{Binding RelativeSource={RelativeSource Self}, Path=Tag}" Foreground="LightGray" />
</VisualBrush.Visual>
</VisualBrush>
</Style.Resources>
<Style.Triggers>
<Trigger Property="Text" Value="{x:Static sys:String.Empty}">
<Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
</Trigger>
<Trigger Property="Text" Value="{x:Null}">
<Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter Property="Background" Value="White" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
What am I missing - why isn't that working ?

For the reusable textbox, you need to create a custom control. Also for binding doesnot work well with visual brush, so you need some temp object to store the value. Refer my below code.
<Window x:Class="ChkList_Learning.Window4"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ChkList_Learning"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
Title="Window4" Height="300" Width="300">
<Window.Resources>
<local:Temp x:Key="temp" Value="{Binding ElementName=Hostname, Path=Watermark}"/>
<Style TargetType="{x:Type local:WatermarkTextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
<Style.Resources>
<VisualBrush x:Key="WatermarkBrush" AlignmentX="Left" AlignmentY="Center" Stretch="None">
<VisualBrush.Visual>
<TextBlock Text="{Binding Source={StaticResource temp}, Path=Value}" FontFamily="Segoe UI" FontSize="20" Foreground="LightGray" Padding="5" />
</VisualBrush.Visual>
</VisualBrush>
</Style.Resources>
<Style.Triggers>
<Trigger Property="Text" Value="{x:Static sys:String.Empty}">
<Setter Property="Background" Value="{StaticResource WatermarkBrush}" />
</Trigger>
<Trigger Property="Text" Value="{x:Null}">
<Setter Property="Background" Value="{StaticResource WatermarkBrush}" />
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter Property="Background" Value="White" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<local:WatermarkTextBox x:Name="Hostname" Height="40" FontFamily="Segoe UI" FontSize="20" VerticalContentAlignment="Center" Watermark="Hello, world.">
</local:WatermarkTextBox>
</Grid>
</Window>
public class Temp : Freezable
{
// Dependency Property
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof(string),
typeof(Temp), new FrameworkPropertyMetadata(string.Empty));
// .NET Property wrapper
public string Value
{
get { return (string)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
protected override System.Windows.Freezable CreateInstanceCore()
{
return new Temp();
}
}
public class WatermarkTextBox : TextBox
{
static WatermarkTextBox()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(WatermarkTextBox), new FrameworkPropertyMetadata(typeof(WatermarkTextBox)));
}
public static readonly DependencyProperty WatermarkProperty = DependencyProperty.Register("Watermark", typeof(string), typeof(WatermarkTextBox));
public string Watermark
{
get { return (string)GetValue(WatermarkProperty); }
set { SetValue(WatermarkProperty, value); }
}
}

Related

IntegerUpDown Control Changing Background When Textbox IsFocused

I'm creating a WPF application and am using the WPF Extended Toolkit library . I have added the IntegerUpDown control to my UserControl and when the user presses inside the textbox I want the background color to change from a dark grey to a light grey.
I have tried adding a style trigger in the xaml that triggers when the IntegerUpDown control IsFocused for the background to change. However, this did not seem to work.
<xctk:IntegerUpDown x:Name="Day" Value="{Binding DayText, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" Style="{StaticResource IntegerUpDownStyle}" Minimum="{Binding MinimumDateSelection}" Maximum="{Binding MaximumDateSelection}">
<xctk:IntegerUpDown.Watermark>
<TextBlock Text="Day" Foreground="{StaticResource OffsetWhiteBrush}" Margin="0,0,60,0"/>
</xctk:IntegerUpDown.Watermark>
</xctk:IntegerUpDown>
<!-- Textbox and PasswordBox base styling for login boxes -->
<Style x:Key="IntegerUpDownStyle" TargetType="{x:Type Control}" BasedOn="{StaticResource BaseTextStyle}">
<Setter Property="MaxWidth" Value="400" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="FontSize" Value="{StaticResource FontSize20}" />
<Setter Property="FontFamily" Value="{StaticResource LatoRegular}" />
<Setter Property="Background" Value="{StaticResource DarkGreyBrush}" />
<Setter Property="Margin" Value="0,20,0,0" />
<Style.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="Background" Value="{StaticResource LightGreyBrush}" />
</Trigger>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.Errors)[0].ErrorContent}" />
</Trigger>
</Style.Triggers>
</Style>
With the styling I've added I expected the background of the control to change from a dark grey to a light grey but nothing happened. How can I make this happen?
I tried this problem in my own app,and it's finished.Here's code:
<Window
x:Class="WpfApp16.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfApp16"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
Title="MainWindow"
Width="800"
Height="450"
mc:Ignorable="d">
<Window.Resources>
<Style x:Key="IntegerUpDownStyle" TargetType="xctk:IntegerUpDown">
<Style.Triggers>
<EventTrigger RoutedEvent="ValueChanged">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetProperty="Background.Color"
From="DarkGray"
To="Transparent"
Duration="0:0:1" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel>
<xctk:IntegerUpDown Width="200" Style="{StaticResource IntegerUpDownStyle}">
<xctk:IntegerUpDown.Background>
<SolidColorBrush Color="Transparent" />
</xctk:IntegerUpDown.Background>
</xctk:IntegerUpDown>
</StackPanel>
For more Information ,look this linke:WPF Animation dependency issue
The same trigger in IntegerUpDown source code, so the outside trigger was no longer effective.
IntegerUpDown source code:
<Trigger Property="IsFocused" Value="True">
<Setter TargetName="PART_TextBox"
Property="FocusManager.FocusedElement"
Value="{Binding ElementName=PART_TextBox}" />
</Trigger>
I tried using GotFocus and LostFocus events.
xaml:
<xctk:IntegerUpDown x:Name="Day"
LostFocus="IntegerUpDown_LostFocus"
GotFocus="IntegerUpDown_GotFocus"
Focusable="True"
Value="{Binding DayText, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" Style="{StaticResource IntegerUpDownStyle}" Minimum="{Binding MinimumDateSelection}" Maximum="{Binding MaximumDateSelection}">
<xctk:IntegerUpDown.Watermark>
<TextBlock Text="Day" Foreground="{StaticResource OffsetWhiteBrush}" Margin="0,0,60,0"/>
</xctk:IntegerUpDown.Watermark>
</xctk:IntegerUpDown>
cs code:
private void IntegerUpDown_GotFocus(object sender, RoutedEventArgs e)
{
Day.Background = new SolidColorBrush(Colors.Gray);
}
private void IntegerUpDown_LostFocus(object sender, RoutedEventArgs e)
{
Day.Background = new SolidColorBrush(Colors.DarkGray);
}
After seeing the answer from #J.B.D I edited the ControlTemplate for the IntegerUpDown control to change the back
<ControlTemplate x:Key="ControlControlTemplate1" TargetType="{x:Type Control}">
<xctk:ButtonSpinner x:Name="PART_Spinner" AllowSpin="{Binding AllowSpin, RelativeSource={RelativeSource TemplatedParent}}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" ButtonSpinnerLocation="{Binding ButtonSpinnerLocation, RelativeSource={RelativeSource TemplatedParent}}" Background="{TemplateBinding Background}" HorizontalContentAlignment="Stretch" IsTabStop="False" ShowButtonSpinner="{Binding ShowButtonSpinner, RelativeSource={RelativeSource TemplatedParent}}" VerticalContentAlignment="Stretch">
<xctk:WatermarkTextBox x:Name="PART_TextBox" AutoMoveFocus="{Binding AutoMoveFocus, RelativeSource={RelativeSource TemplatedParent}}" AutoSelectBehavior="{Binding AutoSelectBehavior, RelativeSource={RelativeSource TemplatedParent}}" AcceptsReturn="False" BorderThickness="0" ContextMenu="{TemplateBinding ContextMenu}" Foreground="{TemplateBinding Foreground}" FontWeight="{TemplateBinding FontWeight}" FontStyle="{TemplateBinding FontStyle}" FontStretch="{TemplateBinding FontStretch}" FontSize="{TemplateBinding FontSize}" FontFamily="{TemplateBinding FontFamily}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" IsTabStop="True" IsUndoEnabled="True" MinWidth="20" MaxLength="{Binding MaxLength, RelativeSource={RelativeSource TemplatedParent}}" Padding="{TemplateBinding Padding}" TextAlignment="{Binding TextAlignment, RelativeSource={RelativeSource TemplatedParent}}" TextWrapping="NoWrap" TabIndex="{TemplateBinding TabIndex}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" WatermarkTemplate="{Binding WatermarkTemplate, RelativeSource={RelativeSource TemplatedParent}}" Watermark="{Binding Watermark, RelativeSource={RelativeSource TemplatedParent}}">
<xctk:WatermarkTextBox.Style>
<Style TargetType="{x:Type xctk:WatermarkTextBox}">
<Setter Property="Background" Value="{StaticResource DarkGreyBrush}" />
<Style.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="Background" Value="{StaticResource LightGreyBrush}" />
</Trigger>
</Style.Triggers>
</Style>
</xctk:WatermarkTextBox.Style>
</xctk:WatermarkTextBox>
</xctk:ButtonSpinner>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderBrush" Value="{DynamicResource {ComponentResourceKey ResourceId=ControlMouseOverBorderKey, TypeInTargetAssembly={x:Type Themes:ResourceKeys}}}"/>
</Trigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding IsReadOnly, RelativeSource={RelativeSource Self}}" Value="False"/>
<Condition Binding="{Binding AllowTextInput, RelativeSource={RelativeSource Self}}" Value="False"/>
</MultiDataTrigger.Conditions>
<Setter Property="IsReadOnly" TargetName="PART_TextBox" Value="True"/>
</MultiDataTrigger>
<DataTrigger Binding="{Binding IsReadOnly, RelativeSource={RelativeSource Self}}" Value="True">
<Setter Property="IsReadOnly" TargetName="PART_TextBox" Value="True"/>
</DataTrigger>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="BorderBrush" Value="{DynamicResource {ComponentResourceKey ResourceId=ControlSelectedBorderKey, TypeInTargetAssembly={x:Type Themes:ResourceKeys}}}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
<Trigger Property="IsFocused" Value="True">
<Setter Property="FocusManager.FocusedElement" TargetName="PART_TextBox" Value="{Binding ElementName=PART_TextBox}"/>
<Setter TargetName="PART_TextBox" Property="Visibility" Value="Hidden" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
Please look at the start of the control template and the WatermarkTextBox. The WatermarkTextBox.Style is what I added to make the background change when the textbox is focused.
To override the COntrolTemplate, right click on the IntegerUpDown Control and then press Edit Template

Wpf - Template property is null in constructor

After the class is initialized, template property returns the correct value but in constructor it always returns null. I tried to call ApplyTemplate() method in constructor but it didn't work.
Can anyone explain how and why that happens?
Is it possible to get template property in constructor correctly?
Thanks in advance!
Style
<Style x:Key="DesignerItemStyle" TargetType="{x:Type dataModel:Component}">
<Style.Resources>
<converter:ComponentHeightConverter x:Key="componentHeightConverter"/>
</Style.Resources>
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="RenderTransformOrigin" Value="0.5,0.5"/>
<Setter Property="MinWidth" Value="10"/>
<Setter Property="MinHeight" Value="10"/>
<Setter Property="Height" Value="5"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type dataModel:Component}">
<StackPanel Orientation="Vertical" DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}">
<Grid x:Name="PART_MainGrid">
<!-- PART_ContentPresenter -->
<ContentPresenter x:Name="PART_ContentPresenter"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Content="{TemplateBinding ContentControl.Content}"
Margin="{TemplateBinding ContentControl.Padding}"
Cursor="Arrow"/>
<!-- PART_ResizeDecorator -->
<Control x:Name="PART_ResizeDecorator"
Visibility="Collapsed"
Template="{StaticResource ResizeDecoratorTemplate}"/>
<!-- PART_DragThumb -->
<c:DragThumb x:Name="PART_DragThumb"
Template="{StaticResource MoveThumbTemplate}"
ToolTip="{Binding ToolTip}"
Cursor="SizeAll"/>
<c:RelativePositionPanel x:Name="PART_ConnectorNames"
Visibility="{Binding Path=(viewModel:ToolbarViewModel.IsPortLabelVisible),
Converter={StaticResource BooleanToVisibilityConverter}}"/>
<!-- PART_ConnectorDecorator -->
<Control x:Name="PART_ConnectorDecorator"
Visibility="Visible" Panel.ZIndex="1000"
Template="{StaticResource ConnectorDecoratorTemplate}"/>
</Grid>
<TextBlock x:Name="PART_NameBlock"
HorizontalAlignment="Center" Visibility="{Binding Path=(viewModel:ToolbarViewModel.IsComponentLabelVisible), Converter={StaticResource BooleanToVisibilityConverter}}"
TextTrimming="CharacterEllipsis" Text="{Binding DisplayedName}" Grid.Row="1">
<TextBlock.RenderTransform>
<TranslateTransform X="5" Y="5"/>
</TextBlock.RenderTransform>
</TextBlock>
</StackPanel>
<ControlTemplate.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Value="True" Binding="{Binding RelativeSource={RelativeSource Self},Path=IsSelected}"/>
<Condition Value="{x:Static sys:Guid.Empty}" Binding="{Binding RelativeSource={RelativeSource Self},Path=ParentID}"/>
</MultiDataTrigger.Conditions>
<Setter TargetName="PART_ResizeDecorator" Property="Visibility" Value="Visible"/>
</MultiDataTrigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="PART_ConnectorDecorator" Property="Visibility" Value="Visible"/>
<Setter TargetName="PART_DragThumb" Property="Visibility" Value="Visible"/>
</Trigger>
<Trigger Property="IsSelected" Value="true">
<Setter TargetName="PART_DragThumb" Property="Visibility" Value="Visible"/>
</Trigger>
<DataTrigger Value="True" Binding="{Binding RelativeSource={RelativeSource Self},Path=IsDragConnectionOver}">
<Setter TargetName="PART_ConnectorDecorator" Property="Visibility" Value="Visible"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Concrete Class
public Component()
{
var template = this.Template; //Here template property returns null
}
You can call UpdateDefaultStyle() method before accessing Template property.
e.g.:
var button= new Button();
button.UpdateDefaultStyle();
button.Template // template is not null here
You can override OnApplyTemplate method and access template inside this method.
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
var template = Template; // template is not null here
}

The content property is more than once

following is the code, which is showing the error i.e
: The content property is more than once
Code :
<Window x:Class="Trigger.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Style x:Key="ButtonStyle" TargetType="{x:Type Button}">
<Style.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Opacity" Value="0.5" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
<Grid>
<Button x:Name="PropertyTriggerButton" Width="160" Height="40" Margin="20,0,0,0" HorizontalAlignment="Left" Content="IsPressed Property"
Cursor="Hand" FontWeight="Bold" Style="{StaticResource ButtonStyle}" ToolTip="Press To Raise Property Trigger">
</Button>
</Grid>
</Window>
The Window element can host only one child. You need to put the Style in the resources. Something like this will do:
<Window.Resources>
<Style x:Key="ButtonStyle" TargetType="{x:Type Button}">
<Style.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Opacity" Value="0.5" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
Put this right after the starting tag of the Window element or just before the closing tag of the Window element.
The full code should be like this:
<Window x:Class="Trigger.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style x:Key="ButtonStyle" TargetType="{x:Type Button}">
<Style.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Opacity" Value="0.5" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<Button x:Name="PropertyTriggerButton" Width="160" Height="40" Margin="20,0,0,0" HorizontalAlignment="Left" Content="IsPressed Property"
Cursor="Hand" FontWeight="Bold" Style="{StaticResource ButtonStyle}" ToolTip="Press To Raise Property Trigger">
</Button>
</Grid>
</Window>
Add style inside Window.Resources
<Window.Resources>
<Style x:Key="ButtonStyle" TargetType="{x:Type Button}">
<Style.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Opacity" Value="0.5" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid >
<Button x:Name="PropertyTriggerButton" Width="160" Height="40" Margin="20,0,0,0" HorizontalAlignment="Left" Content="IsPressed Property"
Cursor="Hand" FontWeight="Bold" Style="{StaticResource ButtonStyle}" ToolTip="Press To Raise Property Trigger">
</Button>
</Grid>

WPF: IsPressed trigger of ControlTemplate not working

I use a custom control named ImageButton to display a button with different images. ImageButton contains dependency properties:
public ImageSource DisabledImageSource
{
get { return (ImageSource)GetValue(DisabledImageSourceProperty); }
set { SetValue(DisabledImageSourceProperty, value); }
}
public ImageSource NormalImageSource
{
get { return (ImageSource)GetValue(NormalImageSourceProperty); }
set { SetValue(NormalImageSourceProperty, value); }
}
public ImageSource HoverImageSource
{
get { return (ImageSource)GetValue(HoverImageSourceProperty); }
set { SetValue(HoverImageSourceProperty, value); }
}
public ImageSource PushedImageSource
{
get { return (ImageSource)GetValue(PushedImageSourceProperty); }
set { SetValue(PushedImageSourceProperty, value); }
}
public static readonly DependencyProperty DisabledImageSourceProperty =
DependencyProperty.Register("DisabledImageSource", typeof(ImageSource), typeof(ImageButton), new UIPropertyMetadata());
public static readonly DependencyProperty NormalImageSourceProperty =
DependencyProperty.Register("NormalImageSource", typeof(ImageSource), typeof(ImageButton), new UIPropertyMetadata());
public static readonly DependencyProperty HoverImageSourceProperty =
DependencyProperty.Register("HoverImageSource", typeof(ImageSource), typeof(ImageButton), new UIPropertyMetadata());
public static readonly DependencyProperty PushedImageSourceProperty =
DependencyProperty.Register("PushedImageSource", typeof(ImageSource), typeof(ImageButton), new UIPropertyMetadata());
It's style is defined as follows:
<Style TargetType="{x:Type local:ImageButton}">
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<Image Name="image" Source="{Binding NormalImageSource, RelativeSource={RelativeSource TemplatedParent}}" Stretch="None" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="image" Property="Source" Value="{Binding DisabledImageSource, RelativeSource={RelativeSource TemplatedParent}}"/>
</Trigger>
<Trigger Property="Button.IsPressed" Value="True">
<Setter TargetName="image" Property="Source" Value="{Binding PushedImageSource, RelativeSource={RelativeSource TemplatedParent}}"/>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="True" />
</MultiTrigger.Conditions>
<Setter TargetName="image" Property="Source" Value="{Binding HoverImageSource, RelativeSource={RelativeSource TemplatedParent}}"/>
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Every thing works fine except IsPressed. I can never see the image I set in PushedImageSource and I can't figure out why.
Any help would be appriciated :)
EDIT 1:
Here's the xaml code that tests it
<Window x:Class="SMEClient.WPF.Tester.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:is="clr-namespace:Project1.SearchBox;assembly=Project1"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/Project1;component/SearchBox/ImageButton.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<StackPanel>
<is:ImageButton NormalImageSource="C:\Users\Public\Pictures\Sample Pictures\Koala.jpg"
PushedImageSource="C:\Users\Public\Pictures\Sample Pictures\Chrysanthemum.jpg"
HoverImageSource="C:\Users\Public\Pictures\Sample Pictures\Jellyfish.jpg"/>
</StackPanel>
</Grid>
</Window>
Your triggers are not mutual exclusive, in this case the order in which triggers are added to the Triggers collection comes into play. Your last trigger IsMouseOver overrides the Source property after IsPressed trigger setts the correct image, since a button is Pressed only if the mouse is over (when using mouse of course).
Try setting the IsPressed trigger last in the Triggers collection, and the IsPressed trigger will be applied even though IsMouseOver is also true.
OK, so I found a workaround which is kind of ugly, but it works
<Style TargetType="{x:Type local:ImageButton}">
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<Image Name="Normal" Source="{Binding NormalImageSource, RelativeSource={RelativeSource TemplatedParent}}" Stretch="None" Visibility="Visible" />
<Image Name="Hover" Source="{Binding HoverImageSource, RelativeSource={RelativeSource TemplatedParent}}" Stretch="None" Visibility="Hidden"/>
<Image Name="Clicked" Source="{Binding PushedImageSource, RelativeSource={RelativeSource TemplatedParent}}" Stretch="None" Visibility="Hidden"/>
<Image Name="Disabled" Source="{Binding DisabledImageSource, RelativeSource={RelativeSource TemplatedParent}}" Stretch="None" Visibility="Hidden"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Normal" Property="Visibility" Value="Hidden"/>
<Setter TargetName="Hover" Property="Visibility" Value="Visible"/>
<Setter TargetName="Clicked" Property="Visibility" Value="Hidden"/>
<Setter TargetName="Disabled" Property="Visibility" Value="Hidden"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="Normal" Property="Visibility" Value="Hidden"/>
<Setter TargetName="Hover" Property="Visibility" Value="Hidden"/>
<Setter TargetName="Clicked" Property="Visibility" Value="Visible"/>
<Setter TargetName="Disabled" Property="Visibility" Value="Hidden"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="Normal" Property="Visibility" Value="Hidden"/>
<Setter TargetName="Hover" Property="Visibility" Value="Hidden"/>
<Setter TargetName="Clicked" Property="Visibility" Value="Hidden"/>
<Setter TargetName="Disabled" Property="Visibility" Value="Visible"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Setting HotTracking for a tab control

I am attempting to implement HotTracking for a tab control in Wpf. My understanding is this was not included in the wpf tabcontrol and I would like to use it.
For my benefit HotTracking = When mouseover an unselected tab the tab will change color(usually to something between selected and not selected)
I used a bit of my own knowledge and this post How to set MouseOver event/trigger for border in XAML? but I can't seem to make it work.
This is everything.
<Window x:Class="TestingWpF.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="1024" Width="1280">
<Window.Resources>
<Style TargetType="{x:Type TabItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid>
<Border
Name="Border"
CornerRadius="6,6,0,0" >
<ContentPresenter x:Name="ContentSite"
VerticalAlignment="Center"
HorizontalAlignment="Center"
ContentSource="Header"
Margin="12,2,12,2"/>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Border" Property="Background" Value="LightBlue" />
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter TargetName="Border" Property="Background" Value="AliceBlue" />
</Trigger>
<Trigger Property=" Border.IsMouseOver" Value="True">
<Setter Property="Border.Background" Value="Green" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<TabControl Grid.ColumnSpan="2" Grid.RowSpan="2" Height="309" HorizontalAlignment="Left" Name="tabControl1" VerticalAlignment="Top" Width="781" Padding="0">
<TabItem Header="tabItem1" >
</TabItem>
<TabItem Header="tabItem2" >
</TabItem>
</TabControl>
</Grid>
</Window>
I figured it out, my problem was this section
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Border" Property="Background" Value="LightBlue" />
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter TargetName="Border" Property="Background" Value="AliceBlue" />
</Trigger>
<Trigger Property=" Border.IsMouseOver" Value="True">
//Change this line
//<Setter Property="Border.Background" Value="Green" />
//To This
<Setter TargetName="Border" Property="Background" Value="Green" />
</Trigger>
The last Trigger was the one not working. And if you notice I used different properties in the setter. I changesd it to match the other two and it worked

Categories

Resources