WPF how to style mouse over for 2 different controllers - wpf

So i have ListView, inside each Row i have NumericUpDown:
xmlns:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
<ListView.Resources>
<DataTemplate x:Key="MyDataTemplate2">
<Grid>
<Controls:NumericUpDown
Minimum="0"
Maximum="50"
Value="{Binding Path=Speed}"
StringFormat="N1"
Width="50"
MinWidth="50"
Height="17"
Interval="0.1"
HorizontalAlignment="Left"
HideUpDownButtons="True"
Margin="15,0,0,0"/>
<TextBlock Grid.Column="1" Margin="0,-4,0,0" Text="{Binding Path=Value, ElementName=sliderColumn, StringFormat={}x{0:N0}}"
FontSize="11" Foreground="Gainsboro" VerticalAlignment="Center" HorizontalAlignment="Left" />
</Grid>
</DataTemplate>
</ListView.Resources>
And in my ListView.ItemContainerStyle trigger for Mouse Over:
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="Foreground" Value="White"></Setter>
<Setter Property="Background" Value="#FF103766"/>
<Setter Property="BorderBrush" Value="#FF103766"/>
<Setter Property="BorderThickness" Value="0"/>
</MultiTrigger>
So i want inside this Trigger also change my NumericUpDown Background color when my mouse is over specific Row.
is it possible ?

A binding with relativesource should do the trick
<Controls:NumericUpDown
Minimum="0"
Maximum="50"
Value="{Binding Path=Speed}"
StringFormat="N1"
Width="50"
MinWidth="50"
Height="17"
Interval="0.1"
HorizontalAlignment="Left"
HideUpDownButtons="True"
Margin="15,0,0,0">
<Controls:NumericUpDown.Style>
<Style TargetType="Controls:NumericUpDown">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=ListBoxItem}, Path=IsMouseOver}" Value="true">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Controls:NumericUpDown.Style>
</Controls:NumericUpDown>

Related

WPF mouse hover canvas

i could not find answers on SO anywhere - how do i make hover effect for each "item"
i want that when i hover over canvas (data template, positioned inside grid) to change color on both rectangles that are inside canvas - only place where IsMouseOver works is where i set ContentPresenter, and there i can change size of Grid, and thats all. I cannot get IsMouseOver on canvas to change color of rectangles inside. Anyhow, i am just begginer, so, i know something is wrong, ContentPresenter maybe is the one that takes style trigger, i just do not know how to fix this.
<Border Background="#1C222E">
<Viewbox Grid.Column="0" Grid.Row="0" Name="SeatsBox">
<Viewbox.RenderTransform>
<ScaleTransform ScaleX="1.0" ScaleY="1.0"/>
</Viewbox.RenderTransform>
<ItemsControl ItemsSource="{Binding Seats}" Name="SeatsItems">
<ItemsControl.RenderTransform>
<TranslateTransform X="0" Y="0" />
</ItemsControl.RenderTransform>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid local:GridHelpers.RowCount="{Binding RowCount}" HorizontalAlignment="Center" VerticalAlignment="Center" local:GridHelpers.ColumnCount="{Binding ColumnCount}" ShowGridLines="False" Background="#1C222E" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Grid.Row" Value="{Binding RowEx}" />
<Setter Property="Grid.Column" Value="{Binding ColumnEx}" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Width" Value="60"/>
</Trigger>
</Style.Triggers>
<Style.Resources>
<Style TargetType="{x:Type Rectangle}">
<Setter Property="Width" Value="200" />
<Setter Property="Fill" Value="Blue" />
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=Canvas}, Path=IsMouseOver}" Value="True">
<Setter Property="Fill" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Style.Resources>
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Canvas Width="30" Height="30" Margin="4" Background="Transparent" Tag="{Binding ID}">
<Rectangle Name="RecTop" Canvas.Top="4" Canvas.Left="1" Width="28" Height="18" Fill="#5D606D" Stroke="#5D606D" RadiusX="2" RadiusY="2"></Rectangle>
<Rectangle Name="RecBot" Canvas.Top="23" Canvas.Left="1" Width="28" Height="7" Fill="#5D606D" Stroke="#5D606D" RadiusX="2" RadiusY="2"></Rectangle>
<!-- <TextBlock Text="{Binding Path=Column}" TextWrapping="Wrap" TextAlignment="Center" VerticalAlignment="Center" /> -->
</Canvas>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Status}" Value="Taken">
<Setter TargetName="RecTop" Property="Stroke" Value="#2E3441" />
<Setter TargetName="RecTop" Property="Fill" Value="#2E3441" />
<Setter TargetName="RecBot" Property="Stroke" Value="#2E3441" />
<Setter TargetName="RecBot" Property="Fill" Value="#2E3441" />
</DataTrigger>
<DataTrigger Binding="{Binding Status}" Value="Reserved">
<Setter TargetName="RecTop" Property="Stroke" Value="#5D606D" />
<Setter TargetName="RecBot" Property="Stroke" Value="#5D606D" />
<Setter TargetName="RecTop" Property="Fill" Value="Transparent" />
<Setter TargetName="RecBot" Property="Fill" Value="Transparent" />
</DataTrigger>
<DataTrigger Binding="{Binding Status}" Value="Broken">
<Setter TargetName="RecTop" Property="Stroke" Value="#1885FF" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Viewbox>
</Border>
You've actually already done it properly, the problem is that you're setting Fill explicitly in the Rectangle declarations:
<Rectangle ... Fill="#5D606D" ...></Rectangle>
<Rectangle ... Fill="#5D606D" ...></Rectangle>
Those fields have precedence over what you've set in your style, remove them and your code works fine.

Check my ListView progress-bar cell backgroung color based on property

So i have this cell Progress-Bar inside my ListView.Resources:
<DataTemplate x:Key="MyDataTemplate">
<Grid Margin="-6,0,0,0" Height="20.5" Width="80">
<ProgressBar Name="progressBarColumn"
Maximum="100"
Value="{Binding Progress, UpdateSourceTrigger=PropertyChanged}"
Width="{Binding Path=Width, ElementName=ProgressCell}"
Background="{Binding Path=IsCkecked}"
Margin="0,0,0,0"
Style="{StaticResource CustomProgressBar}" />
<TextBlock Text="{Binding Path=Value, ElementName=progressBarColumn, StringFormat={}{0:N1}%}"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Foreground="{DynamicResource ProgressBarForegroundColor}"
FontFamily="{DynamicResource ProgressBarFontFamily}"
FontSize="{DynamicResource ProgressBarFontSize}"
Margin="{DynamicResource ProgressBarMargin}"/>
</Grid>
</DataTemplate>
And my style:
<Style x:Key="CustomProgressBar" TargetType="ProgressBar">
<Setter Property="Template" >
<Setter.Value>
<ControlTemplate TargetType="ProgressBar">
<Border BorderBrush="{DynamicResource ProgressBorderBrushColor}" BorderThickness="0" Background="{DynamicResource ProgressBackgroundColor}" CornerRadius="0" Padding="0">
<Grid x:Name="PART_Track">
<Rectangle x:Name="PART_Indicator" HorizontalAlignment="Left">
<Rectangle.Style>
<Style TargetType="Rectangle">
<Setter Property="Fill" Value="{DynamicResource ProgressBarFillColor}"/>
<Style.Triggers>
<DataTrigger Value="100" Binding="{Binding Path=Value, RelativeSource={RelativeSource AncestorType=ProgressBar}}">
<Setter Property="Fill" Value="{DynamicResource ProgressBarFillCompleteColor}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
</Rectangle>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Now inside my ListView each binding object has this bool property IsChecked which is another CheckBox cell and when this CheckBox is Unchecked my IsChecked property is false and in this case i wan to change my Progress-Bar Background color.
So this is what i have try and add into my Progress-Bar style (not effect at all on my Progress-Bar Background color...):
<DataTrigger Value="False" Binding="{Binding Path=IsChecked, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=CheckBox}}">
<Setter Property="Fill" Value="Red"/>
</DataTrigger>
EDIT:
My CheckBox is already bind into my property:
IsChecked="{Binding Path=IsChecked}"
...
<DataTrigger Value="True" Binding="{Binding Path=IsChecked}">
<Setter Property="Fill" Value="Red"/>
</DataTrigger>
<DataTrigger Value="False" Binding="{Binding Path=IsChecked}">
<Setter Property="Fill" Value="Yellow"/>
</DataTrigger>
public bool IsChecked
{
get { return _isChecked; }
set
{
_isChecked = value;
OnPropertyChanged();
}
}
after a little bit of work here is the solution:
<Style x:Key="CustomProgressBar" TargetType="ProgressBar">
<Style.Triggers>
<DataTrigger Value="True" Binding="{Binding Path=IsChecked}">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
<DataTrigger Value="False" Binding="{Binding Path=IsChecked}">
<Setter Property="Background" Value="Yellow"/>
</DataTrigger>
</Style.Triggers>
<Setter Property="Template" >
<Setter.Value>
<ControlTemplate TargetType="ProgressBar">
<Border BorderBrush="{DynamicResource ProgressBorderBrushColor}" BorderThickness="0" Background="{DynamicResource ProgressBackgroundColor}" CornerRadius="0" Padding="0">
<Grid x:Name="PART_Track">
<Rectangle x:Name="PART_Indicator" HorizontalAlignment="Left">
<Rectangle.Style>
<Style TargetType="Rectangle">
<Setter Property="Fill" Value="{Binding}"/>
</Style>
</Rectangle.Style>
</Rectangle>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

change properties inside datatemplate of listboxItem if selected

I have the following style:
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock x:Name="Text" Text="{Binding Name}" Margin="0, 5" FontSize="16"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
I want to change the foreground color of "Text" if the "ListBoxItem" is selected. I know from here: Change WPF DataTemplate for ListBox item if selected how to change the DataTemplate. but since I just want to change colors, this solution makes unnecessary duplication in codd - It would be a greater problem if my DataTemplate would be very complex and long.
How do I achieve change of a single property of an object inside the DataTemplate?
If you actually want the same item template always (whether the item is selected or not), but you want a different foreground color when the item is selected, that's easy. Don't set the ContentTemplate in a trigger, because ContentTemplate doesn't change. Just set the foreground color with a trigger. If you don't mess with the foreground color in the template, it will inherit whatever the ListBoxItem has for that property.
<Style TargetType="ListBoxItem">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock
x:Name="Text"
Text="{Binding Name}"
Margin="0, 5"
FontSize="16"
/>
</DataTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
A more elaborate version of the same style:
<Style TargetType="ListBoxItem">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Ellipse
Height="12"
Width="12"
VerticalAlignment="Center"
x:Name="Ellipse"
Fill="Yellow"
Stroke="DeepSkyBlue"
StrokeThickness="1"
/>
<TextBlock
x:Name="Text"
Text="{Binding Name}"
Margin="5,5,0,5"
FontSize="16"
/>
</StackPanel>
<DataTemplate.Triggers>
<DataTrigger
Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=ListBoxItem}}"
Value="True"
>
<Setter
TargetName="Ellipse"
Property="Stroke"
Value="Orange"
/>
<Setter
TargetName="Ellipse"
Property="StrokeThickness"
Value="3"
/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>

How to trap button click event inside listbox item template

I have listbox with textbox inside to display list items. I want to have editable textbox , So I put button inside listbox for selected textbox. I want to trigger button click event for that listbox but I couldn't. Here is my code:
<ListBox HorizontalAlignment="Left" Name="ListTwo" Height="auto" Margin="134.53,15.934,0,0" VerticalAlignment="Top" Width="202.308" ItemsSource="{Binding . ,Source=CollectionUrl,BindsDirectlyToSource=True}" BorderThickness="0" >
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="50" />
</Grid.ColumnDefinitions>
<RadioButton>
<TextBox Name="TextBoxList" Text="{Binding Path=urlString, Mode=TwoWay}" Width="150">
<TextBox.Style>
<Style TargetType="TextBox">
<Style.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="Foreground" Value="Black"/>
<Setter Property="IsReadOnly" Value="False" />
<Setter Property="BorderThickness" Value="0.5"/>
</Trigger>
<Trigger Property="IsFocused" Value="False">
<Setter Property="Foreground" Value="Gray"/>
<Setter Property="IsReadOnly" Value="True" />
<Setter Property="BorderThickness" Value="0"/>
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
</RadioButton>
<Button Content="Save" Grid.Column="1" Tag="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=ListBox}}" Click="Button_Click_2">
<Button.Style>
<Style TargetType="Button">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=TextBoxList, Path=IsFocused}" Value="True">
<Setter Property="Visibility" Value="Visible" />
<Setter Property="ClickMode" Value="Press"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Anyone knows how can I trap click event of button?
Did you try adding an event for Button in the ListBox. This will capture the event.
Button.Click="OnClick"
So like this:
<ListBox HorizontalAlignment="Left" Name="ListTwo" Height="auto" Margin="134.53,15.934,0,0" VerticalAlignment="Top" Width="202.308" ItemsSource="{Binding . ,Source=CollectionUrl,BindsDirectlyToSource=True}" BorderThickness="0" Button.Click="OnClick">
Then your event:
private void OnClick(object sender, RoutedEventArgs e)
{
var originalSource = e.OriginalSource;
// Do your work here
}
However, you have a second problem. Your button style is preventing your event from firing. It works without the style but doesn't fire with the style. Change the style to be on ListBoxItem.IsSelected. Then make it so if you select a TextBox the ListBoxItem is selected.
<ListBox HorizontalAlignment="Left" Name="ListTwo" Height="auto" Margin="134.53,15.934,0,0" VerticalAlignment="Top" Width="202.308" ItemsSource="{Binding . ,Source=CollectionUrl,BindsDirectlyToSource=True}" BorderThickness="0" Button.Click="OnClick">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="50" />
</Grid.ColumnDefinitions>
<RadioButton>
<TextBox Name="TextBoxList" Text="{Binding Path=urlString, Mode=TwoWay}" Width="150">
<TextBox.Style>
<Style TargetType="TextBox">
<Style.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="Foreground" Value="Black"/>
<Setter Property="IsReadOnly" Value="False" />
<Setter Property="BorderThickness" Value="0.5"/>
</Trigger>
<Trigger Property="IsFocused" Value="False">
<Setter Property="Foreground" Value="Gray"/>
<Setter Property="IsReadOnly" Value="True" />
<Setter Property="BorderThickness" Value="0"/>
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
</RadioButton>
<Button Content="Save" Grid.Column="1">
<Button.Style>
<Style TargetType="Button">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}, Path=IsSelected}" Value="True">
<Setter Property="Visibility" Value="Visible" />
<Setter Property="ClickMode" Value="Press"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsKeyboardFocusWithin, RelativeSource={RelativeSource Self}}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="(ListBoxItem.IsSelected)">
<DiscreteBooleanKeyFrame KeyTime="0" Value="True"/>
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
Hope that helps.
You have several options to do it but I'll just give you the two best ones without using third party frameworks.
First is through System.Windows.Interactions and put it inside the TextBox. This will be handled in your ViewModel
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click" >
<i:InvokeCommandAction Command="{Binding ClickCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
Second is through using EventSetter, this will be handled behind the View
<Style TargetType="ListBoxItem">
<EventSetter Event="MouseDoubleClick" Handler="TextBoxClick"/>
</Style>

Wpf TreeView IsExpanded

I tried to bind to IsExpanded property in Hierarchical template with another context.
<HierarchicalDataTemplate x:Key="TreeView1" ItemsSource="{Binding Path=Folders}" >
<StackPanel Margin="5,5,5,5" Orientation="Horizontal">
<StackPanel Name="spinCont">
<ModulesUpToDateChecker1:Spinner Width="20" x:Name="Spin" FolderContext="{Binding}" StateContext="{Binding Path=State}"></ModulesUpToDateChecker1:Spinner>
<Image x:Name="imgFolderIcon" Width="16" Visibility="Hidden"
Source="/ModulesUpToDateChecker;component/Resources/FolderClosed16.png">
<Image.Triggers>
</Image.Triggers>
</Image>
<Image VerticalAlignment="Center" x:Name="imgFolderItem"
Source="{Binding Path=State, Converter={StaticResource stateFolderConverter}}">
<Image.Style>
<Style TargetType="{x:Type Image}">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=IsLast}" Value="true"></Condition>
</MultiDataTrigger.Conditions>
<Setter Property="Visibility" Value="Collapsed"></Setter>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</StackPanel>
<StackPanel DataContext="{Binding Path=Modules}">
<ModulesUpToDateChecker1:Spinner Width="20">
<ModulesUpToDateChecker1:Spinner.Style>
<Style TargetType="{x:Type ModulesUpToDateChecker1:Spinner}">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Animation}" Value="True" >
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</ModulesUpToDateChecker1:Spinner.Style>
</ModulesUpToDateChecker1:Spinner>
<Image VerticalAlignment="Center"
Source="{Binding Path=State, Converter={StaticResource stateImageConverter}}">
<Image.Style>
<Style TargetType="{x:Type Image}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Animation}" Value="True" >
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</StackPanel>
<TextBlock Text="{Binding Path=Name}" Margin="10,0,0,0"></TextBlock>
</StackPanel>
<HierarchicalDataTemplate.Triggers>
<!--<Trigger Property="{Binding}" Value="true">
<Setter TargetName="imgFolderIcon" Property="Source" Value="/ModulesUpToDateChecker;component/Resources/Error.png" />
</Trigger>-->
**<DataTrigger Binding="{Binding Path=IsExpanded}" Value="true">
<Setter TargetName="imgFolderIcon" Property="Source" Value="/ModulesUpToDateChecker;component/Resources/Error.png" />
</DataTrigger>**
doest work
</HierarchicalDataTemplate.Triggers>
</HierarchicalDataTemplate>
I have the "Folder" context (its hierarchical object) but how can i bind to theTreeView properties in HierarchicalDataTemplate.Triggers? When i start this, output shows that there is no IsExpanded property in Folder object. So, i have wrong context.
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=TreeViewItem}, Path=IsExpanded}" Value="true">
<Setter TargetName="imgFolderIcon" Property="Source" Value="/Resources/FolderExpanded.png" />
</DataTrigger>
Easy

Resources