Hover over label change rectangle background gradient - c#

I have a rectange with several labels and images over it, and I have it so that when the user hovers their mouse over the rectangle the background changes to a gradient:
<Rectangle Height="88" HorizontalAlignment="Left" Margin="54,28,0,0" Name="rectangle2" VerticalAlignment="Top"
Width="327" Cursor="Hand">
<Rectangle.Style>
<Style TargetType="{x:Type Rectangle}">
<Setter Property="Fill" Value="Transparent" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Fill">
<Setter.Value>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="White" Offset="0.0" />
<GradientStop Color="#eee" Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
</Rectangle>
However, when I hover over one of the labels that is over the rectangle the background gradient does not show.
I want to make it so that the gradient shows when hovering over the labels as well as the rectangle.
Is this possible?

If by "over" you mean overlayed and not above you can wrap the contents in a Grid (for above you could do this as well i guess, but you should define rows & columns) and use a DataTrigger which triggers if the mouse is over the wrapping grid and not only the rectangle itself, e.g.:
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<Rectangle Width="100" Height="100" StrokeThickness="1" Stroke="Black">
<Rectangle.Style>
<Style TargetType="{x:Type Rectangle}">
<Setter Property="Fill" Value="Transparent" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsMouseOver, RelativeSource={RelativeSource AncestorType=Grid}}" Value="True">
<Setter Property="Fill">
<Setter.Value>
<!-- Brush here -->
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
</Rectangle>
<Label Name="label" Content="This is a Label" />
</Grid>
Alternatively if the label is overlayed you can make mouse events pass through the Label by setting IsHitTestVisible to false.

Because the other elements are on top of the rectangle, I think you will need to hook to the PreviewMouseMove event for the rectangle.
UIELement.PreviewMouseMove: http://msdn.microsoft.com/en-us/library/system.windows.uielement.previewmousemove.aspx
Preview events: http://msdn.microsoft.com/en-us/library/ms752279.aspx

Related

How to change the image of a button when a textbox is empty in WPF?

I want to create a SearchBox and currently my code looks like below. I tried to change the ImageSource of the ImageBrush tag when the text box is empty but I don't know to bind the Text property from the Textbox properly. I want my SearchBox to look like this:
When the SearchBox is empty the button must to show the search image and when the SearchBox is not empty the button must to show the clear search image. Can anyone hepl me with this?
<TextBox Name="SearchTextBox" />
<Button Grid.Column="0" Style="{DynamicResource NoChromeButton}" BorderThickness="1"
VerticalAlignment="Center" HorizontalAlignment="Right" Width="25" Height="25" Click="Search_Click" Panel.ZIndex="1">
<Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<Border>
<Grid>
<ContentPresenter />
<Grid x:Name="StatusPanel" Background="Black" Opacity="0"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="StatusPanel" Property="Opacity" Value="0.1"/>
</Trigger>
<Trigger Property="IsPressed" Value="true">
<Setter TargetName="StatusPanel" Property="Opacity" Value="0.3"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
<Button.Content>
<Rectangle x:Name="aaa" >
<Rectangle.Fill>
<ImageBrush ImageSource="pack://application:,,,/AssemblyName;component/Resources/Img1.png" />
</Rectangle.Fill>
<Rectangle.Style>
<Style TargetType="{x:Type Rectangle}" >
<Style.Triggers>
<DataTrigger Binding="{Binding Text.Length, ElementName=SearchTextBox, UpdateSourceTrigger=PropertyChanged}" Value="0" >
<DataTrigger.Setters>
<Setter Property="Fill">
<Setter.Value>
<ImageBrush ImageSource="pack://application:,,,/AssemblyName;component/Resources/Img2.png" />
</Setter.Value>
</Setter>
</DataTrigger.Setters>
</DataTrigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
</Rectangle>
</Button.Content>
</Button>
you are close. instead of setting <Rectangle.Fill> locally, use Style setter:
<Rectangle x:Name="aaa" >
<Rectangle.Style>
<Style TargetType="{x:Type Rectangle}" >
<Setter Property="Fill">
<Setter.Value>
<ImageBrush ImageSource="pack://application:,,,/AssemblyName;component/Resources/Img1.png" />
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding Text.Length, ElementName=SearchTextBox}" Value="0" >
<DataTrigger.Setters>
<Setter Property="Fill">
<Setter.Value>
<ImageBrush ImageSource="pack://application:,,,/AssemblyName;component/Resources/Img2.png" />
</Setter.Value>
</Setter>
</DataTrigger.Setters>
</DataTrigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
</Rectangle>
it is necessary because Trigger cannot override local value

WPF TabItem border isn't reflecting BorderThickness property

I've got a TabControl with several TabItems. I'm trying to make them have a flatter design. The idea is to have the outside border of the tab go away, with the active tab indicated by a green line at the bottom of the tab. I've been able to get the green line to work perfectly, but no matter what I do I can't get rid of the left, top, and right lines of each TabItem.
Due to text formatting constraints in my specs, I have wrapped the TabItem header into a TextBlock wrapped by a Border. I suspect this combination may have something to do with it. If there is a way to show the green bottom border on the active tab, while allowing line breaks (each tab has two words that need to be split into two lines) and text centering in the tab header, I am totally fine with changing my configuration. I've tried various combinations of the BorderThickness, Margin, and Padding properties to no avail.
<TabControl HorizontalAlignment="Stretch" VerticalContentAlignment="Stretch" x:Name="tabControl">
<TabItem MaxWidth="55" HorizontalAlignment="Center" Background="White">
<TabItem.Header>
<Border Style="{StaticResource TabItemText}">
<TextBlock TextAlignment="Center" Text="Actions Needed" TextWrapping="Wrap"></TextBlock>
</Border>
</TabItem.Header>
</TabItem>
</TabControl>
This is the tab coloring code. It does some redundant things at the moment, but it illustrates what I'm trying to do.
<Style x:Key="TabItemText" TargetType="{x:Type Border}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=TabItem}}" Value="True">
<Setter Property="BorderBrush" Value="#57B481"/>
<Setter Property="BorderThickness" Value="0 0 0 4"/>
<Setter Property="Margin" Value="0 0 0 -3"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=TabItem}}" Value="False">
<Setter Property="BorderThickness" Value="0 0 0 0"/>
<Setter Property="Margin" Value="0 0 0 -3"/>
</DataTrigger>
</Style.Triggers>
</Style>
You can/should change the Template of TabItem. It contains a Border and you should fix its BorderThicknessto something like "0,0,0,2". The Last Value determines the height of the green border you are trying to create. You should also set the BorderBrush and BackgroundBrush to be the same. You change the BorderBrush in the Trigger IsSelected==True to your selected Color. Note that there is no need to use a Border in the Header of you TabItem. Just use a TexBlock to control TextWrapping and stuff. There are other minor changes that I explain in the following example:
<TabControl HorizontalAlignment="Stretch" VerticalContentAlignment="Stretch" x:Name="tabControl">
<TabControl.Resources>
<LinearGradientBrush x:Key="LightBrush" StartPoint="0,0" EndPoint="0,1">
<GradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#FFF" Offset="0.0"/>
<GradientStop Color="#EEE" Offset="1.0"/>
</GradientStopCollection>
</GradientBrush.GradientStops>
</LinearGradientBrush>
<SolidColorBrush x:Key="SolidBorderBrush" Color="#888" />
<SolidColorBrush x:Key="WindowBackgroundBrush" Color="#FFF" />
<SolidColorBrush x:Key="DisabledBackgroundBrush" Color="#EEE" />
<SolidColorBrush x:Key="DisabledBorderBrush" Color="#AAA" />
<SolidColorBrush x:Key="DisabledForegroundBrush" Color="#888" />
<ControlTemplate x:Key="simpleTI" TargetType="TabItem">
<Grid>
<Border Name="Border"
BorderThickness="0,0,0,2"
Background="{StaticResource LightBrush}"
BorderBrush="{StaticResource LightBrush}"
CornerRadius="0" >
<ContentPresenter x:Name="ContentSite" Margin="5,0" VerticalAlignment="Center" HorizontalAlignment="Center"
ContentSource="Header" RecognizesAccessKey="True"/>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Border" Property="BorderBrush" Value="#57B481" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="Border" Property="Background" Value="{StaticResource DisabledBackgroundBrush}" />
<Setter TargetName="Border" Property="BorderBrush" Value="{StaticResource DisabledBorderBrush}" />
<Setter Property="Foreground" Value="{StaticResource DisabledForegroundBrush}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</TabControl.Resources>
<TabItem MaxWidth="55" HorizontalAlignment="Center" Background="White" Template="{StaticResource simpleTI}" >
<TabItem.Header>
<TextBlock TextAlignment="Center" Text="Actions Needed" TextWrapping="Wrap" />
</TabItem.Header>
</TabItem>
<TabItem MaxWidth="55" HorizontalAlignment="Center" Background="White" Template="{StaticResource simpleTI}" >
<TabItem.Header>
<TextBlock TextAlignment="Center" Text="Actions Needed 1" TextWrapping="Wrap" />
</TabItem.Header>
</TabItem>
<TabItem MaxWidth="55" HorizontalAlignment="Center" Background="White" Template="{StaticResource simpleTI}" >
<TabItem.Header>
<TextBlock TextAlignment="Center" Text="Actions Needed 2" TextWrapping="Wrap" />
</TabItem.Header>
</TabItem>
</TabControl>
I'm pretty sure you're going to need to override the control template of your TabItem and/or TabControl to accomplish this. See https://msdn.microsoft.com/en-us/library/ms752032.aspx for a starting point.

Button in WPF acting in strange way with isMouseOver

I am having a funny issue here with WPF and a button styled. Problem is it contains a path and isMouseOver seems to only trigger when the mouse pointer is over the path but not over the button. That is I have to move the mouse pointer over the white figure inside the button to have the button shaded. Is as if the button wouldn't exist and only the path would.
This is the code for the button:
<Button Grid.Column="5" x:Name="btnClose" Width="30" Height="30" BorderBrush="White"
BorderThickness="0" Style="{StaticResource MenuButtonStyle}"
Command="{Binding ExitCommand}">
<Path Data="M0,0 L16,16 M16,0 L0,16" Stroke="White" StrokeThickness="3"
Margin="0,1,0,0" StrokeEndLineCap="Round" StrokeStartLineCap="Round" />
</Button>
And this is the style:
<Style x:Key="MenuButtonStyle" TargetType="Button">
<Setter Property="Width" Value="80" />
<Setter Property="Height" Value="80" />
<Setter Property="Margin" Value="0,0,0,0" />
<Setter Property="FontSize" Value="13.5"/>
<Setter Property="Foreground" Value="Red"/>
<Setter Property="RenderTransformOrigin" Value="0.5,0.5"/>
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="ToolTipService.ShowOnDisabled" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border CornerRadius="2.5"
x:Name="ButtonBorder"
BorderThickness="1.2"
RenderTransformOrigin="0.5,0.5">
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0">
<Border x:Name="ButtonShine" Grid.Row="0" VerticalAlignment="Stretch"
HorizontalAlignment="Stretch" >
<!--<Border.Effect>
<DropShadowEffect ShadowDepth="1" BlurRadius="1" RenderingBias="Quality" Direction="270" />
</Border.Effect>-->
</Border>
<ContentPresenter Grid.Row="0" VerticalAlignment="Center"
HorizontalAlignment="Center" />
<Border x:Name="shadowMouseOver" Grid.Row="0" Visibility="Hidden"
VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
Background="#7F171717">
</Border>
<Border x:Name="shadowDisabled" Grid.Row="0" Visibility="Hidden"
VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
Background="#AFFFFFFF">
</Border>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="Button.IsEnabled" Value="false">
<Setter Property="Button.Foreground" Value="#FFDEDEDE" />
<Setter Property="Visibility" TargetName="shadowDisabled" Value="Visible"/>
</Trigger>
<Trigger Property="Button.IsMouseOver" Value="true">
<Setter Property="Visibility" TargetName="shadowMouseOver" Value="Visible"/>
</Trigger>
<Trigger Property="Button.IsPressed" Value="true">
<Setter Property="Button.RenderTransformOrigin" Value="0.5,0.5"/>
<Setter Property="Button.RenderTransform">
<Setter.Value>
<ScaleTransform ScaleX="0.95" ScaleY="0.95"/>
</Setter.Value>
</Setter>
<Setter Property="Visibility" TargetName="shadowMouseOver" Value="Visible"/>
<Setter Property="Background" TargetName="ButtonShine" >
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFBFBFBF" Offset="1"/>
<GradientStop Color="#FF383838"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="BorderBrush" TargetName="ButtonShine" >
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFBFBFBF" Offset="1"/>
<GradientStop Color="#FF383838"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Any ideas? Bug in WPF? Something not done properly?
This is definitely not a bug, but due to the fact that you provide no background for the control in its template for the default state; thus, the hit test fails in the region outside of the path. If you notice, both shadowMouseOver and shadowDisabled, the only two borders that provide any background, are not visible unless the appropriate events are triggered. Thus, they are not visible to hit tests. Your path, on the other hand, is visible and so it's able to trigger events.
See Hit Testing in the Visual Layer at MSDN for more information:
https://msdn.microsoft.com/library/ms752097(v=vs.100).aspx
Just in case that link fails some time in the future, here's one of the parts that pretty much summarizes what I'm trying to say here:
The purpose of the HitTest methods in the VisualTreeHelper class is to
determine whether a geometry or point coordinate value is within the
rendered content of a given object, such as a control or graphic
element. For example, you could use hit testing to determine whether a
mouse click within the bounding rectangle of an object falls within
the geometry of a circle. You can also choose to override the default
implementation of hit testing to perform your own custom hit test
calculations. The following illustration shows the relationship
between a non-rectangular object's region and its bounding rectangle.
You have a couple of options if you wish to maintain the transparent background look. Either set that background to Transparent, due to the fact that transparent objects are visible to hits tests, or set it to some color, while turning its opacity down to 0. Best place for that background would probably be at ButtonBorder (most outer border), but it'll be your decision to make.

WPF Button change Rectangle.OpacityMask when disable

I am not able to manage a solution for my problem.
Here is my Button
<Button BorderBrush="Black" IsDefault="True" IsEnabled="{Binding ContentManager.CanPreview}" x:Name="Preview" Grid.Column="1" Style="{DynamicResource MetroCircleButtonStyle}">
<Button.ToolTip>
<ToolTip>
<StackPanel>
<TextBlock FontWeight="Bold">Preview</TextBlock>
<TextBlock>Preview the selected document</TextBlock>
</StackPanel>
</ToolTip>
</Button.ToolTip>
<Rectangle Margin="1,0,0,0" Width="17" Height="12" Fill="Black">
<Rectangle.OpacityMask>
<VisualBrush Stretch="Fill" Visual="{StaticResource appbar_eye}" />
</Rectangle.OpacityMask>
<Rectangle.Style>
<Style>
<Style.Triggers>
</Style.Triggers>
</Style>
</Rectangle.Style>
</Rectangle>
</Button>
My question is how can I set my trigger to change the <VisualBrush Stretch="Fill" Visual="{StaticResource appbar_eye}" /> when the button is not enable.
Create a Style that targets Rectangle class, move OpacityMask to Style as Setter, otherwise Style.Trigger won't be able to change local value, and create a Trigger on IsEnabled property being false to change OpacityMask to a different Brush
<Rectangle Margin="1,0,0,0" Width="17" Height="12" Fill="Black">
<Rectangle.Style>
<Style TargetType="{x:Type Rectangle}">
<Setter Property="OpacityMask">
<Setter.Value>
<VisualBrush Stretch="Fill" Visual="{StaticResource appbar_eye}" />
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="OpacityMask">
<Setter.Value>
<!-- other brush -->
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
</Rectangle>
Maybe add the other visual brush as resource to your usercontrol/window/app
<Style.Resources>
<VisualBrush x:Key="otherBrush" Stretch="Fill" Visual="{StaticResource other_appbar_eye}" ></VisualBrush>
and use it in the trigger like this
<Rectangle.Style>
<Style TargetType="Rectangle">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="OpacityMask" Value="{StaticResource otherBrush}"/>
</Trigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
and move the default value to the style as well, since you´re not able to change it via trigger otherwise.

Glow effect on MouseEnter WPF

I'm new in WPF(c#). I need make a glow effect around image control using triggers. How can I do make glow effect on mouse-enter event?
I want to use your answer i my style.
My effect is:
<DropShadowEffect x:Key="MyEffect" ShadowDepth="0" Color="Blue" Opacity="1" BlurRadius="20"/>
I see many links but they don't work.
To add glow to Image control you need to set Effect to your DropShadowEffect when IsMouseOver=True, something like this:
<Image Source="/WpfApplication1;component/myimage.png">
<Image.Style>
<Style TargetType="{x:Type Image}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Effect">
<Setter.Value>
<DropShadowEffect ShadowDepth="0" Color="Blue" Opacity="1" BlurRadius="20"/>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
If you want to reuse your effect, you must capture IsMouseOver trigger and set Control.Effect property to what you have defined in your resources.
<Button Width="100" Content="Hello Glow" >
<Button.Style>
<Style>
<Style.Triggers>
<Trigger Property="Button.IsMouseOver" Value="True">
<Setter Property="Button.Effect" Value="{StaticResource MyEffect}" />
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
for this, you must place you effect in recourses of current page/window/usercontrol
<Window.Resources>
<DropShadowEffect x:Key="MyEffect" ShadowDepth="0" Color="Blue" Opacity="1" BlurRadius="20"/>
</Window.Resources>

Categories