Why mouse event is not fired when inside listview? - wpf

I am using System.Windows.Interactivity and i have to display a Message on mouse enter event.
The problem is the same event is called when done outside the ListView, But it gets not called when inside the ListView.
I tried doing so using mvvm approach:
<Grid>
<StackPanel Grid.Row="1" Grid.Column="1" Name="events1">
//This Event works outside the ListView but not inside ListView
<Rectangle Fill="Yellow" Stroke="Black" Width="100" Height="30">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseEnter">
<i:InvokeCommandAction Command="{Binding SomeCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Rectangle>
<ListView BorderBrush="#FF1D93E4" BorderThickness="4" Behaviour:GridViewColumnResize.Enabled="True" ScrollViewer.VerticalScrollBarVisibility="Auto" SelectedItem="{Binding SelectedItem ,Mode=TwoWay}" ItemsSource="{Binding Ur1r2_Obj}" HorizontalContentAlignment="Stretch">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
<ListView.View>
<GridView>
<GridViewColumn Header="State" Behaviour:GridViewColumnResize.Width="*">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Grid Background="{Binding Converter={StaticResource colorToBrushConverter}}">
//The event do not work here
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseEnter">
<i:InvokeCommandAction Command="{Binding SomeCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<Button Margin="35,0,0,0" HorizontalAlignment="Center" Content="{Binding Path=Etat, Mode=OneWay}" Background="{Binding Converter={StaticResource colorToBrushConverter}}" />
</Grid>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</StackPanel>
</Grid>
In view Model
private ICommand someCommand;
public ICommand SomeCommand
{
get
{
//return plotButton;
return someCommand ?? (someCommand = new CommandHandler(() => MyAction2(), _canExecute));
}
set
{
someCommand = value;
OnPropertyChanged("SomeCommand");
}
}
private void MyAction2() //Messsage is popuped on Moseenter event when i try to hover mouse over rectangle outside the listview , But not get called when inside the Listview
{
MessageBox.Show("Yeah Called");
}
Why it event is not called from inside the ListView. How to make it call ?

If you are trying to invoke the same command (SomeCommand) you should specify a RelativeSource of the Binding:
<Grid Background="{Binding Converter={StaticResource colorToBrushConverter}}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseEnter">
<i:InvokeCommandAction Command="{Binding DataContext.SomeCommand,
RelativeSource={RelativeSource AncestorType=ListView}}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<Button Margin="35,0,0,0" HorizontalAlignment="Center" Content="{Binding Path=Etat, Mode=OneWay}" Background="{Binding Converter={StaticResource colorToBrushConverter}}" />
</Grid>
The DataContext of an item in the ListView is an object in your "Ur1r2_Obj" ItemsSource whereas the DataContext of the Rectangle is your view model. That's why the binding fails in your CellTemplate.

Related

Add doubleclick-command to wpf-treeview-items

as I found a lot of tasks (questions) to my question, I still have no idea how that works.
Even it's a much too complex example or simply the needed namespace was missing. So after one hour of research, my question...
How do I intergrate doubleclick-command to my WPF treeview (-items)?
Actually, my tree looks like this:
<!-- used Namespace: xmlns:i="http://schemas.microsoft.com/xaml/behaviors" -->
<TreeView DataContext="{Binding ProjectTree}" ItemsSource="{Binding ProjectNode}" DockPanel.Dock="Left"
x:Name="ProjectTree" Margin="0 0 2 0" Grid.Column="0">
<TreeView.ContextMenu>
<ContextMenu StaysOpen="True">
<MenuItem Header="Löschen" Height="20"
Command="{Binding RemoveNodeCommand}"
CommandParameter="{Binding ElementName=ProjectTree, Path=SelectedItem}">
<MenuItem.Icon>
<Image Source="/Icons/32x32/Remove_32x32.png" Width="15" Height="15"/>
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
</TreeView.ContextMenu>
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectedItemChanged">
<i:InvokeCommandAction Command="{Binding TreeNodeSelectedCommand}"
CommandParameter="{Binding ElementName=ProjectTree, Path=SelectedItem}"/>
</i:EventTrigger>
<i:EventTrigger EventName="MouseDoubleClick">
<i:InvokeCommandAction Command="{Binding UpdateNodeCommand}"
CommandParameter="{Binding ElementName=ProjectTree, Path=SelectedItem}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}"/>
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/>
<Setter Property="FontWeight" Value="Normal"/>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="FontWeight" Value="Bold"/>
</Trigger>
</Style.Triggers>
</Style>
</TreeView.ItemContainerStyle>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<StackPanel Orientation="Horizontal">
<Image Margin="3" Source="{Binding ItemType, Converter={x:Static misc:TreeItemImageConverter.Instance }}" Width="20" />
<TextBlock VerticalAlignment="Center" Text="{Binding Name}"/>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
I don't really understand how the Interaction.Triggers work but should they be the right way?
I'm using the ICommand and a relaycommand for my menu- and button-commands. So far, everything fine in my viewmodels.
Sorry if that is a noob question.
EDIT
As it wasn't a noob question but a noob typo, MouseDoubleClick simply works as SelectedItemChanged so my question was unneccessary. (updated code above)
You can add an interaction trigger in the data template.
I don't have your code so I've adapted a project I already had hanging about to show this working.
My markup, which is of course illustrative rather than cut and paste ready for your purposes:
<TreeView Name="tv" ItemsSource="{Binding Families}" Grid.Row="1" Grid.ColumnSpan="2"
>
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:Family}" ItemsSource="{Binding Members}">
<Border>
<StackPanel Orientation="Horizontal"
Height="32"
>
<Label VerticalAlignment="Center" FontFamily="WingDings" Content="1"/>
<TextBlock Text="{Binding Name}" />
</StackPanel>
</Border>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type local:FamilyMember}">
<ContentControl>
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDoubleClick">
<i:InvokeCommandAction Command="{Binding DataContext.TestCommand, RelativeSource={RelativeSource AncestorType=TreeView}}"
CommandParameter="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType=TreeViewItem}}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<StackPanel Orientation="Horizontal"
Height="32"
x:Name="sp">
<TextBlock Tag="{Binding DataContext.Name,
RelativeSource={RelativeSource AncestorType=TreeViewItem , AncestorLevel=2}
}"
Text="{Binding Name}" />
<TextBlock Text="{Binding Age}" Foreground="Green" />
</StackPanel>
</ContentControl>
</DataTemplate>
</TreeView.Resources>
</TreeView>
The command in my window viewmodel
public class MainWindowViewModel
{
private DelegateCommand<FamilyMember> testCommand;
public ICommand TestCommand
{
get
{
if (testCommand == null)
{
testCommand = new DelegateCommand<FamilyMember>((member) =>
{
MessageBox.Show($"Member's name is {member.Name}");
});
}
return testCommand;
}
}
My tree has family and then each has family members.
If I expand members out I can double click a family member and the message box confirms the name is correct.
Note the contentcontrol in the datatemplate.
You need a control to give you double click support.
Interaction triggers cannot be applied in style setters but you could create an attached behaviour that handles the MouseDoubleClick event for the TreeViewItem:
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="local:YourBehavior.Command" Value="{Binding YourCommand}" />
...
</Style>
Another option is to invoke the command programmtically from the code-behind of the view.

Executing the Button's Command on ListBoxItem Selection

I have this (simplified for SO) listbox:
<ListBox x:Name="CurriculumList"
ItemsSource="{Binding FilteredCurriculums}"
SelectedIndex="0"
SelectionMode="Single"
IsSynchronizedWithCurrentItem="True">
<ListBox.ItemTemplate>
<DataTemplate>
<Button Name="TheButton"
HorizontalContentAlignment="Stretch"
Content="{Binding DisplayMember}"
CommandParameter="{Binding Id}"
Command="{Binding OpenCurriculumEditViewCommand}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I can navigate up and down the listBoxItems with the keyboard to change selection, but it doesn't change the detail view - the Button in the DataTemplate doesn't actually get clicked, so the OpenCurriculumEditViewCommandnever gets executed.
Anyone have any idea how I can do this?
Well, if you want to execute OpenCurriculumEditViewCommand when the ListBox selection changes, you could do the following:
First:
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
And then..
<ListBox x:Name="CurriculumList"
ItemsSource="{Binding FilteredCurriculums}"
SelectedIndex="0"
SelectionMode="Single"
IsSynchronizedWithCurrentItem="True">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction CommandParameter="{Binding Path=SelectedItem.Id, RelativeSource={RelativeSource AncestorType=ListBox}}" Command="{Binding OpenCurriculumEditViewCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ListBox>
You should not use a Button at all if you want it to trigger on selection.

Wpf Close popup when ListboxItem is selected

I have listbox inside popup. How would I close popup right after I select item from list box;
here is code:
<Popup x:Name="ColorPopup" AllowsTransparency="True"
IsOpen="{Binding ElementName=ColorToggle, Path=IsChecked}" Placement="Bottom" StaysOpen="False" PlacementTarget="{Binding ElementName=ColorToggle}">
<Border x:Name="DropDownBorder1" BorderBrush="{DynamicResource {x:Static SystemColors.WindowFrameBrushKey}}" Margin="0, 0,5,5" BorderThickness="1" Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}" Effect="{DynamicResource WindowShadowEffect}">
<ListBox Name="ColorList" VerticalContentAlignment="Stretch" Margin="1, 3, 1, 3" IsEnabled="True" Grid.Column="0" Background="Transparent" HorizontalContentAlignment="Center" SelectedItem="{Binding fColor}" SelectionMode="Single" Style="{StaticResource HorizontalListBoxStyle2}" ItemsSource="{Binding FillColors}">
</ListBox>
</Border>
</Popup>
Subscribe to SelectionChanged event.
you can either do it in code-behind:
private void ListBox_SelectionChanged_1(object sender, SelectionChangedEventArgs e)
{
// ColorPopup.IsOpen = false; ?? or ColorToggle.IsChecked = false;
}
<ListBox SelectionChanged="ListBox_SelectionChanged_1" ... />
or maybe if you use MVVM pattern...
It could be something like this for example for MVVM-Light:
<ListBox ...>
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<cmd:EventToCommand Command="{Binding Path=ClosePopupCommand}" PassEventArgsToCommand="True" />
</i:EventTrigger>
</i:Interaction.Triggers>
</ListBox>
Or Prism could be almost the same :
<ListBox>
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<prism:InvokeCommandAction Command="{Binding Path=ClosePupupCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</ListBox>
Or if you have dirty mind you could also close popup in fColor property setter. :)
public object fColor
{
get
{
return this.fColorField;
}
set
{
this.fColorField= value;
IsColorToggelChecked = false;
RaisePropertyChanged(() => this.fColor);
}
}

Silverlight: Adding ChangePropertyAction to DataTemplate

I was playing around, experimenting and googling this for the last hour and cannot figure out the problem. Basically, I have a listbox, each item has textblock and checkbox. I need to change text of textblock to green next to the checked checkbox. The code below is the best that I could come up with, but it doesn't work. Any help is appreciated.
<DataTemplate x:Key="ListBoxTemplate">
<Grid
Width="80">
<TextBlock
x:Name="textBlock"
HorizontalAlignment="Left"
Text="{Binding Data, Converter={StaticResource DataConverter}}"
Foreground="#FF859FAF"
FontSize="12"
TextWrapping="Wrap"
Width="50"
Margin="0"
Grid.Row="10" />
<CheckBox
x:Name="Btn6"
IsChecked="{Binding IsSelected, Mode=TwoWay}"
Cursor="Hand"
Padding="0"
HorizontalAlignment="Right"
Height="32"
VerticalAlignment="Bottom"
RenderTransformOrigin="0.5,0.5"
Width="26"
d:LayoutOverrides="GridBox">
<i:Interaction.Triggers>
<i:EventTrigger
EventName="textBlock">
<ei:ChangePropertyAction
TargetName="textBlock"
TargetObject="{Binding ElementName=textBlock}"
PropertyName="Width"
Value="100">
</ei:ChangePropertyAction>
<i:InvokeCommandAction
Command="{Binding SelectDataCommand, Source={StaticResource ControlViewModel}}"
CommandName="SelectDateRangeCommand"
CommandParameter="{Binding}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</CheckBox>
(sorry for my bad english)
This do not exactly answer your question but an easy alternative would be to bind IsSelected with the TextBox.Foreground and create a converter that return a SolidColorBrush green when the value is true

ListBox with Button in ItemTemplate: fire SelectedChanged on Button Click

I have a ListBox with Button in ItemTemplate. When I press a Button, some Command fired. I want the ListBox to fire SelectionChanged event when Button Click event happen. How shoult I fire ListBox SelectionChanged event and pass appropriate context?
<ListBox ItemsSource="{Binding SomeSource}" >
<ListBox.ItemTemplate>
<DataTemplate>
<Button Grid.Row="0" BorderThickness="0" Background="Transparent" HorizontalAlignment="Stretch">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<cmd:EventToCommand Command="{Binding SomeCommand}" CommandParameter="{Binding}" PassEventArgsToCommand="True" />
</i:EventTrigger>
</i:Interaction.Triggers>
<Button.Template>
<ControlTemplate>
<TextBlock Text="{Binding Title}" />
</ControlTemplate>
</Button.Template>
</Button>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
If you can have a SelectedItem property in the ViewModel you can TwoWay bind that to the ListBox.Selecteditem and in the SomeCommand implementation you can set the ViewModel.SelectedItem so that it reflects to the UI and you get SelectionChanged call.

Resources