a ActionMessage EventTrigger for ItemDataTemplate - wpf

I have a question for ItemsControl.
If I wan't to Bind the Func Out of Items, like this:
Code:
<Button cal:Action.TargetWithoutContext="{Binding MenuItemX}" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<cal:ActionMessage MethodName="Clicked" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
Link:((Caliburn Micro) Mapping a ActionMessage Methodname to a Child Object of the ViewModel).
But I Bind the TreeView DataTemplate and use a Control MouseClick:
Code:
<HierarchicalDataTemplate x:Key="treeDataTemplate" DataType="{x:Type myData:Music}" ItemsSource="{Binding ChildNode}">
<TextBlock Text="{Binding Name}" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonUp">
<cal:ActionMessage MethodName="TreeItemClick" >
<cal:Parameter Value="{Binding}" />
</cal:ActionMessage>
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBlock>
</HierarchicalDataTemplate>
The problem here is that the TextBlock(in Child ViewModel), the MethodName(in MainViewModel), and the Parameter(in Child ViewModel).
What's the best way to build it?

Related

Why mouse event is not fired when inside listview?

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.

ListView TextBlock context menu is not invoking the bound command

My ListView is binded to ObservableDictionary source. In ListView control, value is bound to TextBlock. The context menu for TextBlock is bound to an event but the event is not being executed on click. Below is the code.
<ListView ItemsSource="{Binding Path=Source, Mode=TwoWay}" Grid.Row="0" Height="300">
<ListView.ItemTemplate>
<DataTemplate>
<WrapPanel>
<TextBlock Text="{Binding Value}">
<TextBlock.ContextMenu>
<ContextMenu>
<MenuItem Header="Delete">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction Command="{Binding Path= MenuClicked}" CommandParameter="Delete"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</MenuItem>
<MenuItem Header="Rename">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction Command="{Binding Path= MenuClicked}" CommandParameter="Rename"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</MenuItem>
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</WrapPanel>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.ContextMenu>
<ContextMenu>
<MenuItem Header="Add">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction Command="{Binding Path= MenuClicked}" CommandParameter="Add"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</MenuItem>
<MenuItem Header="Import">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction Command="{Binding Path= MenuClicked}" CommandParameter="Import"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</MenuItem>
</ContextMenu>
</ListView.ContextMenu>
</ListView>
Try to provide a RelativeSource for your CommandBinding. Something like
<i:InvokeCommandAction Command="{Binding Path=DataContext.MenuClicked, RelativeSource={RelativeSource.FindAncestor, AncestorType=Window}}" CommandParameter="Delete"/>
Replace the AncestoryType=Window with AncestoryType=UserControl if your ListView is inside a UserControl
ContextMenu doesn't get same NameScope as in the UIElement they are defined.
So binding (like ElementName, Ancestor) usually creates the problem. You have to set Name scope first in the code behind:
NameScope.SetNameScope(contextMenu, NameScope.GetNameScope(this));
contextMenu is the x:Name of your context menu.
Then you can use relative source binding or any other binding for command. like below:
Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x: type ListView}},Path=DataContext.MenuClicked}"
PS: If MenuClicked command is defined in the DataContext of ListView.

silverlight combobox invokecommandaction on selectionchanged event cannot pass parameter

I have a combobox, using databinding and MVVM pattern. Everytime the user changes the selection, I added an event trigger, and a command is executed. the code is the following:
<ComboBox x:Name="myComboBox" Width="150" ItemsSource="{Binding Items}" >
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Name}"/>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding LoadCommand}" CommandParameter="{Binding SelectedItem, ElementName=myComboBox}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</ComboBox>
the problem is that the parameter it passes is always null.
I changed the parameter from SelectedItem to SelectedIndex, this way I get the parameter and it is not null. Then i get my object using the index.

RadTreeViewItem, MVVM, and Click events

I'm having trouble getting a click event or mouse down event to fire on a RadTreeViewItem in the ViewModel. What syntax should I be using? This is the relevant XAML below:
<Toolkit:AccordionItem x:Name="Accordion1" Header="{Binding Header, Mode=TwoWay}" Width="200">
<ListBox x:Name="SitesList" Width="195" BorderThickness="0" ItemsSource="{Binding Games, Mode=OneWay}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}">
<ListBox.ItemTemplate>
<DataTemplate>
<telerik:RadTreeView IsDragDropEnabled="True" IsSingleExpandPath="True"
telerikDragDrop:RadDragAndDropManager.AllowDrag="True" PreviewDragEnded="RadTreeView_PreviewDragEnded"
IsDragTooltipEnabled="False">
<telerik:RadTreeViewItem Header="{Binding siteName, Mode=TwoWay}" Tag="{Binding siteKey, Mode=TwoWay}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<cmd:EventToCommand Command="{Binding RadTreeItemClickCommand, Mode=TwoWay}" MustToggleIsEnabledValue="True"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</telerik:RadTreeViewItem>
</telerik:RadTreeView>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Toolkit:AccordionItem>
As far as I can tell, binding the events of the RadTreeViewItem has to be done in code-behind; the ItemPrepared event of RadTreeView is fired when a RadTreeViewItem is created and bindings can be set in a handler. More information here:
http://www.telerik.com/help/silverlight/radtreeview-events-working-with-item-prepared-event.html
Don't bother with the event to command. You can set a command on the RadTreeViewItem directly.

how to send id of button clicked to command?

I've got a button inside a datatemplate. When the button is clicked I'd like to send the id of the button to my command. The snippet below obviously dosn't work. What am i doing wrong?
<DataTemplate>
<Button CommandParameter="ProductId" x:Name="btnProduct" Width="180" Height="40" Content="{Binding DisplayText}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<n:ExecuteCommandAction Command="{Binding ShowSandwichPriceCommand}"
Parameter="{Binding ElementName=btnProduct, Path=SelectedValue}"
/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</DataTemplate>
The button element doesn't have the SelectedValue property.
You might want to use the Name propery instead or some other available property.
<DataTemplate>
<Button CommandParameter="ProductId" x:Name="btnProduct" Width="180" Height="40" Content="{Binding DisplayText}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<n:ExecuteCommandAction Command="{Binding ShowSandwichPriceCommand}"
Parameter="{Binding ElementName=btnProduct, Path=Name}"
/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</DataTemplate>
Hope this helps
i was able to get my code working with this. thanks.
<DataTemplate>
<Button Command="{Binding DataContext.ShowSandwichPriceCommand, RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type ItemsControl}}}"
CommandParameter="{Binding Path=ProductId}"
Content="{Binding DisplayText}">
</Button>
</DataTemplate>

Resources