Trigger event in ViewModel when ListBoxItem has hover over - wpf

Issue
I have a Listbox that displays a list of images. I want to be able to hover over an image and for it to display the image in a bigger size. I am able to get the hover effect and for it to display some text i entered, but i need the image to change for different ListBoxItems.
Code
Here is the code I have used to get the hover effects:
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Padding" Value="5,0,5,5" />
<Setter Property="Height" Value="140"/>
<Setter Property="Width" Value="200"/>
<Style.Triggers>
<Trigger Property="Control.IsMouseOver" Value="True">
<Setter Property="ToolTip" Value="{Binding IMAGEHERE}"></Setter>
<Setter Property="Control.Background" Value="#d64b36" />
</Trigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
So as you can see I have the tooltip but i need to image to be bound to the value from the ViewModel.
If an event in my ViewModel could get triggered when I hovered over a ListBoxItem it should solve my issue.

I think you can set the ToolTip with the Image control.
<Style.Triggers>
<Trigger Property="Control.IsMouseOver" Value="True">
<Setter Property="Control.ToolTip">
<Setter.Value>
<Image Source="{Binding Imagepath}" />
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
then, you can pass the source as Imagepath property from your ViewModel. I haven't tested this.

Related

WPF Datagrid adding BorderBrush to row causes row to shift on IsMouseOver

I want to find a way to highlight my data grid rows when I hover over them. The closest thing I found was adding a border to the datagrid row. However, in doing so it causes the row I am hovering over to shift to the right, slightly. On top of that it shows a horizontal scrollbar to appears at the bottom.
this is what I'm doing to the datagrid
<Style x:Key="DefaultRowStyle" TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Background" Value="LightSlateGray" />
<Setter Property="BorderThickness" Value="2" />
</Trigger>
</Style.Triggers>
</Style>
My question is this: is there another way to highlight the datagrid row?
This is due to the element resizing when a border is added to it. The easiest option is to add a permanent border and make it visible or transparent.
<Style x:Key="DefaultRowStyle" TargetType="{x:Type DataGridRow}">
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderThickness" Value="2" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Background" Value="LightSlateGray" />
</Trigger>
</Style.Triggers>
</Style>

How to bind Background color to another IsSelected Background

I want to bind the selected Background color of MyDataGrid to another IsSelected Background color so they share the same color. I'm thinking it can be done something like below. How can I do it?
<DataGrid.Resources>
<Style TargetType="{x:Type DataGridCell}">
<Style.Triggers>
<Trigger Property="DataGridCell.IsSelected" Value="True">
<Setter Property="Background" Value="{Binding ElementName=OtherDataGrid, Path=??Background??" />
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.Resources>
The best way to share the background is to use a StaticResource.
You can create a brush in resources and refer that in both the data grids.
Like:
<Style.Triggers>
<Trigger Property="DataGridCell.IsSelected" Value="True">
<Setter Property="Background" Value="{StaticResource selectedCellBackground}" />
</Trigger>
</Style.Triggers>
Another way is to declare a notify property in the view model and bind both colors to it.

A problem with using triggers in XAML

At the code below, when a mouse is over the grid, the grid's Background is expected to be red, but it isn't executed as expected.
<Grid>
<Grid.Style>
<Style TargetType="{x:Type Grid}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
</Grid.Style>
</Grid>
However, if I added the Setter to make the Background green, it would be executed properly.
<Grid>
<Grid.Style>
<Style TargetType="{x:Type Grid}">
<Setter Property="Background" Value="Green"/><!-- at the former, added code-->
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
</Grid.Style>
</Grid>
I don't know why it is, but guess that there is a precedence for setting the Background, causing the issue. Here is Dependency Property Value Precedence from MSDN, and I understand the precedence of of that reference, but I cannot link this issue to the precedence(MSDN).
Additionally, at above the code snippets, if the Grid is replaced with a Button, both these code will not be executed as expected.
UPDATED: Adding Button case about this issue
<Button>
<Button.Style >
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="Transparent"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
The problem is your Grid has a null background, so it is not visible for mouse hit testing. If you set the Background to Transparent, then it will be hit-testable like when you set it to green.
More information can be found here.
I tried your Button and the Background is initialized to Transparent properly. The Red value is only shown for a fraction of a second. This is because in the Aero theme (I'm on Windows 7) the Button's ControlTemplate uses a custom chrome to provide animated state transitions (i.e. when hovering etc). This custom chrome element uses internal brushes and it ignores the Background property.
This has nothing to do with property precedence. For the Grid, it's simply a matter of your Grid not being hit-testable. So it's IsMouseOver will not be set to true, unless it has a non-null background (or a child which renders something).
You can see the Precedence in action here:
<Grid Background="Blue">
<Grid.Style>
<Style TargetType="{x:Type Grid}">
<Setter Property="Background" Value="Green"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
</Grid.Style>
</Grid>
In the above, the Grid will always be Blue as that has the highest precedence (i.e. local or #3). While Red (#6) takes precedence over Green (#8).
In the case of the Button, you have something like this:
<Button Background="Blue">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="border" Background="{TemplateBinding Background}">
<ContentPresenter />
</Border >
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border" Property="Background" Value="Red"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Button.Style>
</Button>
In this case, there are two Background properties in play: the Button and the Border in the control template. The Button's Background property is used by the Border by default, but when the mouse is hovering it uses a Red brush. At that point, it doesn't matter what the value of the Button's Background property is set to.

Expand the combobox and its items when it gets focus

I want to expand the height of the combobox whenever the combobox gets the Focus.
I have used the following code to expand the combobox height.
<Style TargetType="{x:Type ComboBox}">
<Style.Triggers>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="RenderTransform">
<Setter.Value>
<ScaleTransform ScaleX="1" ScaleY="2" />
</Setter.Value>
</Setter>
<Setter Property="RenderTransformOrigin" Value="0.5,0.5"/>
<Setter Property="Panel.ZIndex" Value="99999"/>
</Trigger>
</Style.Triggers>
</Style>
Problem:
When i put the focus on the Combobox first time, the combobox item list opened in normal mode. But if i again click on the combobox then combobx item list opened and also list items height is expanded.
But i want the combobox list items to be expanded even in the first click (focus) also. Also combobox height must be in expanded mode even when i select the item in the Combobox item.
Thanks in advance
Is this what you want?
<Style TargetType="{x:Type ComboBox}">
<Style.Triggers>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="IsDropDownOpen" Value="true" />
</Trigger>
</Style.Triggers>
</Style>
</ComboBox.Style>

'Graying Out' a WPF button image?

I have a simple Button control that contains an Image object as its content. I want so set the Image opacity to 0.5 when the Button is disabled to provide an additional visual cue as to the Button status.
What is the simplest way to accomplish that result in XAML? Thanks for your help.
Use a trigger in the Image style. (It would be more natural to put it in the Button style, but the Button style can't easily affect the Image for annoying technical reasons. It could be done in the Button's ControlTemplate but that's overkill for what you want here.)
<Button>
<Image Source="something.png">
<Image.Style>
<Style TargetType="Image">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="0.5" />
</Trigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</Button>
Note we are taking advantage here of the fact that the Image will be disabled when the Button is disabled, so we can trigger directly on the Image's own IsEnabled property. In other cases, the Button property we want to trigger on might not be inherited by the Image; in that case, we'd need to use a DataTrigger with the FindAncestor RelativeSource to bind to the containing button.
If you want something more generic, put this in your resources section for your window or UserControl .
<UserControl.Resources>
<Style x:Key="ImageEnabled" TargetType="Image">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="0.25"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
And in the actual button just do this
<Button>
<Image Source="{StaticResource LinkImage}" Style="{StaticResource ImageEnabled}"/>
</Button>
Here's a more generic style you can apply:
<Style TargetType="Button">
<Style.Resources>
<Style TargetType="Image">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="0.5" />
</Trigger>
</Style.Triggers>
</Style>
</Style.Resources>
</Style>
If you want the entire button greyed out, styling the button itself has worked for me. It seems to grey out all button content.
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value=".75"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
previous solutions only change opacity and not the color of the image, to gray out an image one need to convert the image to grayscale as follow. I did it for a toggleButton but the same method can be used on a button.
<ToggleButton>
<ToggleButton.Style>
<Style TargetType="{x:Type ToggleButton}">
<Setter Property="Content">
<Setter.Value>
<Image
RenderOptions.BitmapScalingMode="HighQuality"
RenderOptions.EdgeMode="Aliased"
Source="/Resources/imageForButton.png"
Stretch="UniformToFill" />
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsChecked" Value="False">
<Setter Property="Content">
<Setter.Value>
<Image
RenderOptions.BitmapScalingMode="HighQuality"
RenderOptions.EdgeMode="Aliased"
Stretch="UniformToFill">
<Image.Source>
<FormatConvertedBitmap
x:Name="myImageFormat"
DestinationFormat="Gray8"
Source="/Resources/imageForButton.png" />
</Image.Source>
</Image>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</ToggleButton.Style>
</ToggleButton>

Resources