how to send id of button clicked to command? - wpf

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>

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.

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.

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.

a ActionMessage EventTrigger for ItemDataTemplate

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?

mvvm light PassEventArgsToCommand break app in ListBoxDragDropTarget

Hi I'm trying to pass eventargs to comman that I bind in ViewModel. Everything works fine if I don't use PassEventArgsToCommand="True". But If put PassEventArgsToCommand="True" than app break. Did you have similar problem?
<Controls:ListBoxDragDropTarget Grid.Column="1" AllowDrop="true" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="Drop">
<GalaSoft_MvvmLight_Command:EventToCommand Command="{Binding PersonDrop, Mode=OneWay}" PassEventArgsToCommand="True" />
</i:EventTrigger>
</i:Interaction.Triggers>
<ListBox x:Name="fromListBox" ItemsSource="{Binding Person, Mode=TwoWay}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name, Mode=TwoWay}"></TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Controls:ListBoxDragDropTarget>
Ok. I found out. I used System.Windows.DragEventArgs instead of Microsoft.Windows.DragEventArgs as argument in my command.

Resources