Expand the combobox and its items when it gets focus - wpf

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>

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>

Trigger event in ViewModel when ListBoxItem has hover over

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.

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.

Trigger for a ContextMenu Visibility?

I have a Listbox that starts off with no items inside. When a user uses the GUI to select a value from a combobox and clicks the add Button, the the listbox gets an item added. The Listbox also has a contextmenu set.
How can i use XAML to make sure that the Listbox.contextmenu.Visibility property set to hidden when there are no items in the listbox??
UPDATE
I actually used this code in the end. Please comment on its appropriatness
<Style TargetType="ListBox">
<Style.Resources>
<ContextMenu x:Key="cm">
<MenuItem Header="Buy"/>
<MenuItem Header="Sell"/>
</ContextMenu>
</Style.Resources>
<Setter Property="ContextMenu" Value="{StaticResource cm}"/>
<Style.Triggers>
<Trigger Property="ListBox.HasItems" Value="False">
<Setter Property="ContextMenu.Visibility" Value="Hidden"/>
</Trigger>
</Style.Triggers>
</Style>
I do not think that messing with the visibility of the ContextMenu is a good idea, just null out the whole menu if the list is empty.
e.g.
<Style TargetType="{x:Type ListBox}">
<Style.Resources>
<ContextMenu x:Key="cm">
<!-- Menu here -->
</ContextMenu>
</Style.Resources>
<Setter Property="ContextMenu" Value="{StaticResource cm}" />
<Style.Triggers>
<DataTrigger Binding="{Binding Items.Count, RelativeSource={RelativeSource Self}}" Value="0">
<Setter Property="ContextMenu" Value="{x:Null}" />
</DataTrigger>
</Style.Triggers>
</Style>
You could also choose to only define ContextMenus on the items themselves using the ItemContainerStyle, then no ContextMenu can be opened without items but that might of course not fit your scenario.

How to determine index of current ListBox item from DataTemplate?

I have a ListBox. Now I want to write a DataTemplate in such way, that the first item will have red background and white background for other items. I guess I need to write a DataTrigger, but I have no idea how do determine that DataTemplate is applying to the first item.
items controls have an alternation count that you use to style against
have a look here :
<Style TargetType="{x:Type ListBoxItem}">
<Style.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="0">
<Setter Property="Background" Value="LightBlue"></Setter>
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Background" Value="LightGreen"></Setter>
</Trigger>
</Style.Triggers>
</Style>
enjoy!

Resources