How to trap button click event inside listbox item template - wpf

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>

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.

Fill button into a datagrid cell

I have a data grid and for the column HCode I have/need buttons, but the property Code can be null/empty in which case the Button will not be visible.
I'd like to know if there are options or defining a mouse-click handler for the cell is the way to go.
Below is the DataGridTemplate defining the column
<DataGridTemplateColumn Header="HCode" MinWidth="120">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Content="{Binding Code}"
Style="{StaticResource BStyle}"
Background="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=TextBlock}, Path=Background}"
Click="ButtonBase_OnClick"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Center"
/>
<!--Visibility="{qc:Binding '$P != null && $P.Length > 0 ? Visibility.Visible : Visibility.Collapsed', P={Binding Code}}"-->
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
Below is the style that is used
<Style x:Key="BStyle"
TargetType="{x:Type Button}">
<Setter Property="SnapsToDevicePixels"
Value="true" />
<Setter Property="BorderThickness"
Value="0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="120*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="30*"></RowDefinition>
</Grid.RowDefinitions>
<ContentPresenter Margin="0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
RecognizesAccessKey="True" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Foreground"
Value="Blue" />
<Style.Triggers>
<Trigger Property="IsMouseOver"
Value="true">
<Setter Property="Foreground"
Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
You could define two DataTriggers. Try this:
<Button Content="{Binding Code}"
Background="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=TextBlock}, Path=Background}"
Click="ButtonBase_OnClick"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Center">
<Button.Style>
<Style TargetType="Button" BasedOn="{StaticResource BStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding Code}" Value="{x:Null}">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
<DataTrigger Binding="{Binding Code.Length}" Value="0">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
Or:
<DataTrigger Binding="{Binding Code.Length, FallbackValue=0}" Value="0">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>

WPF how to style mouse over for 2 different controllers

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>

Rectangle Datatrigger Fill binded to Textblock text

I would like to change the fill of a rectangle based on a Textblock text
My Textblock
<TextBlock Name="lblOk" Text="OK" Foreground="Black" FontSize="20" FontWeight="Medium" />
My Datatrigger:
<Style x:Key="RectangleFill" TargetType="Rectangle">
<Setter Property="Fill" Value="Blue"></Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName="lblOk, Path=Text}" Value="OK">
<Setter Property="Fill" Value="#FF008C00" />
</DataTrigger>
</Style.Triggers>
</Style>
My Datatrigger doesnt work, seems the Path=Text is wrong. What is the correct Path?
Please check this code, it is working
<Window.Resources>
<Style x:Key="RectangleFill" TargetType="Rectangle">
<Setter Property="Fill" Value="Blue" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=lblOk, Path=Text}" Value="OK">
<Setter Property="Fill" Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel>
<TextBlock Name="lblOk" Text="OK" Foreground="Black" FontSize="20" FontWeight="Medium" />
<Rectangle Width="100"
Height="50" Style="{StaticResource RectangleFill}">
<Rectangle.Resources>
</Rectangle.Resources>
</Rectangle>
</StackPanel>
My code is working. I had typo mistake as shwon in comment.
<Style x:Key="RectangleFill" TargetType="Rectangle">
<Setter Property="Fill" Value="Blue"></Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=lblOk, Path=Text}" Value="OK">
<Setter Property="Fill" Value="#FF008C00" />
</DataTrigger>
</Style.Triggers>
</Style>

How can I "Click Through" a control in WPF?

I have an order entry form that has a ListBox with a list of line items. I have my items template, and one of the values is a ComboBox in each of my Items.
Now, my form can also create Credit memo's in addition to purchase orders, but when I am creating a credit memo, I want to put the words "Credit Memo" over the list box, however, the TextBlock covers the ComboBox in two of my line items. I would like to pass my click event through the TextBlock to the ComboBoxes but I'm not sure how to do it.
This is what I have, ( Maybe I am coming at this totally wrong, I am kinda a noob with WPF )
<ListBox SelectionMode="Single" Grid.Row="2"
ItemsSource="{Binding Path=LineItems}" HorizontalContentAlignment="Stretch"
IsSynchronizedWithCurrentItem="True" Background="#66FFFFFF">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Background" Value="WhiteSmoke"/>
<Setter Property="BorderThickness" Value="1" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsPartBackOrder}" Value="True">
<Setter Property="Background" Value="Orange" />
</DataTrigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate DataType="{x:Type Entities:SalesOrderLineItem}" >
<OrderEntry:SalesOrderLineItemCreate DataContext="{Binding}" DeleteSalesOrderLineItem="DeleteSalesOrderLineItem" Margin="0,3,3,0" >
<OrderEntry:SalesOrderLineItemCreate.Resources>
<Style TargetType="{x:Type OrderEntry:SalesOrderLineItemCreate}">
<Style.Triggers>
<DataTrigger
Binding="{Binding RelativeSource=
{
RelativeSource
Mode=FindAncestor,
AncestorType={x:Type ListBoxItem}
},
Path=IsSelected
}" Value="True">
<Setter Property="Background" Value="LightBlue" />
<Setter Property="Foreground" Value="Black" />
</DataTrigger>
</Style.Triggers>
</Style>
</OrderEntry:SalesOrderLineItemCreate.Resources>
</OrderEntry:SalesOrderLineItemCreate>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<TextBlock Grid.Row="2"
Text="Credit Memo"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="48" Height="Auto"
FontStyle="Italic"
Foreground="Red"
Opacity=".25">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=OrderType}" Value="CR">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=OrderType}" Value="CU">
<Setter Property="Visibility" Value="Hidden" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<TextBlock IsHitTestVisible="False" .../>

Resources