I have a context menu which is binded to a list of items. When I click on an item, the command executes however I am having problems passing the selected item as a parameter, can anyone identify what I'm doing wrong?
I have tried passing {Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}} as the command parameter however it just gives me the whole list within the context menu and when. When I tried {Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type MenuItem}}} no value was seen.
<ContextMenu x:Key="SelectFileTab" ItemsSource="{Binding ContextMenuItems}" x:Name="contextmenu">
<ContextMenu.ItemTemplate>
<DataTemplate>
<MenuItem Header="{Binding}">
</MenuItem>
</DataTemplate>
</ContextMenu.ItemTemplate>
<i:Interaction.Triggers>
<i:EventTrigger EventName="PreviewMouseUp">
<i:InvokeCommandAction Command="{Binding SelectedFileToAdd, Mode=OneWay}" CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ContextMenu>
I really over complicated something quite simple, there was no need to use interaction.triggers issue to the command, all I needed to do was
<ContextMenu x:Key="SelectFileTab" ItemsSource="{Binding ContextMenuItems}" x:Name="contextmenu">
<ContextMenu.ItemTemplate>
<DataTemplate>
<MenuItem Header="{Binding}" Command="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=DataContext.SelectedFileToAdd}"
CommandParameter="{Binding RelativeSource={RelativeSource Self}}"/>
</DataTemplate>
</ContextMenu.ItemTemplate>
</ContextMenu>
Related
Using WPF, I have a checkbox within a combobox and I keep getting a data binding error when trying to bind a command in a checkbox back to my view model. Here's the error
'OnComboMultiSelectCheckedCommand' property not found on 'object' ''String' (HashCode=-66358460)'. BindingExpression:Path=OnComboMultiSelectCheckedCommand;
DataItem='String' (HashCode=-66358460);
target element is 'InvokeCommandAction' (HashCode=61927311);
target property is 'Command' (type 'ICommand')
Here's an excerpt from the XAML
<ComboBox Name="comboMultiSelectBox" SelectedItem="{Binding TargetValue, UpdateSourceTrigger=LostFocus}">
<ComboBox.Style>
<Style TargetType="ComboBox">
<Style.Triggers>
<DataTrigger Binding="{Binding TargetPropert}" Value="Weather">
<Setter Property="ItemsSource" Value="{Binding WeatherList}"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ComboBox.Style>
<ComboBox.ItemTemplateSelector>
<customControls:ComboBoxItemTemplateSelector>
<customControls:ComboBoxItemTemplateSelector.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox Content="{Binding}"/>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Checked">
<i:InvokeCommandAction Command="{Binding OnComboMultiSelectCheckedCommand}"></i:InvokeCommandAction>
</i:EventTrigger>
<i:EventTrigger EventName="Unchecked">
<i:InvokeCommandAction Command="{Binding Path = OnComboMultiSelectUncheckedCommand}"></i:InvokeCommandAction>
</i:EventTrigger>
</i:Interaction.Triggers>
</StackPanel>
</DataTemplate>
</customControls:ComboBoxItemTemplateSelector.ItemTemplate>
<customControls:ComboBoxItemTemplateSelector.SelectedItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text ="{Binding TextForDisplay}"></TextBlock>
</StackPanel>
</DataTemplate>
</customControls:ComboBoxItemTemplateSelector.SelectedItemTemplate>
</customControls:ComboBoxItemTemplateSelector>
</ComboBox.ItemTemplateSelector>
</ComboBox>
I have used a Template selection technique as described in #1012 (https://wpf.2000things.com/?s=combobox).
The itemsource for the combo box (WeatherList) is just a list of strings and the binding for the combobox is definitely working. The problem is that the checkbox is not picking up the commands I have defined in the viewmodel and I get the binding error as described above.
Thanks
Several tips and suggestions here:
You are missing the /CheckBox closure
Try using
{Binding ElementName=comboMultiSelectBox, Path=OnComboMultiSelectCheckedCommand }.
<CheckBox Content="{Binding}"/>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Checked">
<i:InvokeCommandAction Command="{Binding ElementName=comboMultiSelectBox, Path=OnComboMultiSelectCheckedCommand }" />
</i:EventTrigger>
<i:EventTrigger EventName="Unchecked">
<i:InvokeCommandAction Command="{Binding ElementName=comboMultiSelectBox, Path=OnComboMultiSelectUncheckedCommand }" />
</i:EventTrigger>
</i:Interaction.Triggers>
</CheckBox>
Create a viewmodel for each WeatherListItem so events can be handled in this dedicated viewmodel itself.
How Command parameter can be bind to the selected index in ListBox? My code:
<ListBox>
<i:Interaction.Triggers>
<i:EventTrigger
EventName="MouseDoubleClick">
<i:InvokeCommandAction
Command="{
Binding Path=SelectPath,
Mode=OneTime,
RelativeSource={
RelativeSource Mode=FindAncestor,
AncestorType={x:Type UserControl}
}
}"
CommandParameter="ListBox.SelectedIndex" // how can this parameter be bind to SelectedIndex
/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ListBox>
EDIT:
What I did and it works: created new dp property SelectedListBoxIndex bind it with SelectedIndex and then pass property as command parameter. But is there a better way to do it?
<ListBox
SelectedIndex="{
Binding Path=SelectedListBoxIndex,
RelativeSource={
RelativeSource Mode=FindAncestor,
AncestorType={x:Type UserControl}
}}">
<i:Interaction.Triggers>
<i:EventTrigger
EventName="MouseDoubleClick">
<i:InvokeCommandAction
Command="{
Binding Path=SelectPath,
Mode=OneTime,
RelativeSource={
RelativeSource Mode=FindAncestor,
AncestorType={x:Type UserControl}
}
}"
CommandParameter="{
Binding Path=SelectedListBoxIndex,
RelativeSource={
RelativeSource Mode=FindAncestor,
AncestorType={x:Type UserControl}
}
}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</ListBox>
One way could be setting your ListBox x:Name and then binding CommandParameter to its SelectedIndex property like this:
<ListBox x:Name="lb">
<i:Interaction.Triggers>
<i:EventTrigger
EventName="MouseDoubleClick">
<i:InvokeCommandAction
Command="{
Binding Path=SelectPath,
Mode=OneTime,
RelativeSource={
RelativeSource Mode=FindAncestor,
AncestorType={x:Type UserControl}
}
}"
CommandParameter="{Binding ElementName=lb, Path=SelectedIndex}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</ListBox>
I'm getting a the following error when I use Interactivity:
Error Collection property 'System.Windows.Controls.Canvas'.'Triggers'
is null.
Here's my code:
<ItemsControl x:Name="StreamCanvasItemSource" ItemsSource="{Binding StreamCanvasItems, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="{Binding ActualWidth, ElementName=StreamImage}" Height="{Binding ActualHeight, ElementName=StreamImage}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas x:Name="StreamCanvas" Background="Transparent" Width="{Binding ActualWidth, ElementName=StreamImage}" Height="{Binding ActualHeight, ElementName=StreamImage}"
AuxiliaryUtils:SizeObserver.Observe="True" AuxiliaryUtils:SizeObserver.ObservedWidth="{Binding CurrentCanvasWidth, Mode=OneWayToSource}"
AuxiliaryUtils:SizeObserver.ObservedHeight="{Binding CurrentCanvasHeight, Mode=OneWayToSource}"
AuxiliaryUtils:SizeObserver.ObservedLeft="{Binding CanvasLeft, Mode=OneWayToSource}" AuxiliaryUtils:SizeObserver.ObservedTop="{Binding CanvasTop, Mode=OneWayToSource}">
<Interactivity:Interaction.Triggers>
<Interactivity:EventTrigger EventName="PreviewMouseWheel">
<Command:EventToCommand Command="{Binding OnMouseWheelCommand}" PassEventArgsToCommand="True" />
</Interactivity:EventTrigger>
<Interactivity:EventTrigger EventName="PreviewMouseDown">
<Interactivity:InvokeCommandAction Command="{Binding OnMouseDownCommand}" CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Canvas}}}"/>
</Interactivity:EventTrigger>
<Interactivity:EventTrigger EventName="PreviewMouseMove">
<Interactivity:InvokeCommandAction Command="{Binding OnMouseMoveCommand}" CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Canvas}}}"/>
</Interactivity:EventTrigger>
<Interactivity:EventTrigger EventName="PreviewMouseUp">
<Interactivity:InvokeCommandAction Command="{Binding OnMouseUpCommand}" CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Canvas}}}"/>
</Interactivity:EventTrigger>
</Interactivity:Interaction.Triggers>
</Canvas>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
The thing is that everything works as expected when I run the program, I see the error when compiling, and I can't see the designer unless I comment the Interactivity block.
Any idea why?
How is the datacontext connected to the window/page? it would it advisable to add the following line to the window/page and setting IsDesignTimeCreatable to true:
d:DataContext="{d:DesignInstance Type=yourviewmodetype, IsDesignTimeCreatable=True}"
In this way the view will bind to the values of the viewmodel in designtime which is exactly what is going wrong atm in your application.
The following Xaml code allows me to use a context menu in a listview and send the row details as an object to the view model:
<ListView.ContextMenu>
<ContextMenu>
<MenuItem Header="Link This Operation"
Command="{Binding SelectedOperation}"
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=ContextMenu}, Path=PlacementTarget.SelectedItem}"/>
</ContextMenu>
</ListView.ContextMenu>-->
However i want to do the same thing through a double mouse click. I have tried all sorts. Including this:
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDoubleClick">
<i:InvokeCommandAction Command="{Binding SelectedItem}"
CommandParameter="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=PlacementTarget.SelectedItem}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
This works but the object is always null.
Any ideas?
Try this one:
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDoubleClick">
<i:InvokeCommandAction Command="{Binding SelectedOperation}"
CommandParameter="{Binding RelativeSource={RelativeSource Self}, Path=SelectedItem}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
I have a DataTemplate that represents AppBar buttons that I declare through a collection of custom AppBarCommand objects.
public AppBarCommand(RelayCommand command, string buttonstyle)
{
Command = command;
ButtonStyle = buttonstyle;
}
<DataTemplate>
<Button Command="{Binding Command}"
Style="{Binding ButtonStyle, Converter={StaticResource StringNameToStyleConverter}}"/>
</DataTemplate>
I would like to add a CommandParameter binding, but the parameter has to be the Button itself. This is so I can set the PlacementTarget of a Callisto flyout. Is this possible?
<Button Command="{Binding Command}"
CommandParameter="{Binding RelativeSource={RelativeSource Self}}" />
Your Command property should be the generic version of the RelayCommand: RelayCommand<object> for instance.
Answer like Miklós Balogh said, or you can:
<Button x:Name="MyButton" Command="{Binding Command}" CommandParameter={Binding ElementName=MyButton ... />
I had the same problem but I used it in a bit different context:
<MenuItem ItemsSource="{Binding MyList}">
<MenuItem.ItemContainerStyle>
<Style TargetType="{x:Type MenuItem}">
<Setter Property="Command" Value="{Binding RelativeSource={ RelativeSource FindAncestor, AncestorType={ x:Type Window}}, Path= DataContext.MyListItemCommand}"/>
<Setter Property="CommandParameter" Value="{Binding}" />
</Style>
</MenuItem.ItemContainerStyle>
</MenuItem>
so I assume that even if you write it like this
<Button Command="{Binding Command}" CommandParameter="{Binding}" />
it should work.
I also recommend reading this post to understand it better.