WPF Command Binding of ContextMenu Item inside ItemsControl - c#

My Application consists of a MainWindow with a ContentControl and I change the ViewModel depending on the selected menu.
One of the UserControls I display as content contains the following WrapPanel:
<UserControl ...>
<Grid>
<WrapPanel>
<ItemsControl ItemsSource="{Binding Connections}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Command="{Binding DataContext.ConnectionSelectCommand, RelativeSource={RelativeSource AncestorType=ItemsControl}}"
CommandParameter="{Binding}"
FocusManager.FocusedElement="{Binding ElementName=InstanceName}"
Style="{DynamicResource DashboardButton}">
<TextBlock TextWrapping="Wrap" HorizontalAlignment="Center" Text="{Binding Name}" />
<Button.ContextMenu>
<ContextMenu>
<MenuItem Header="Delete"
Command="{Binding ConnectionRemoveCommand}"
CommandParameter="{Binding}" />
</ContextMenu>
</Button.ContextMenu>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</WrapPanel>
</Grid>
</UserControl>
The Command on the ContextMenu doesn't work because it tries to call ConnectionRemoveCommand on the Connection object instead of the ConnectionViewModel which is the DataContext of the UserControl.
How do I bind the Command to the ConnectionViewModel with the CommandParameter being the Connection object?

If you bind the Tag property of the Button to the DataContext of the ItemsControl, you could then bind to it using the PlacementTarget of the ContextMenu:
<Button Command="{Binding DataContext.ConnectionSelectCommand, RelativeSource={RelativeSource AncestorType=ItemsControl}}"
CommandParameter="{Binding}"
FocusManager.FocusedElement="{Binding ElementName=InstanceName}"
Style="{DynamicResource DashboardButton}"
Tag="{Binding DataContext, RelativeSource={RelativeSource AncestorType=ItemsControl}}">
<TextBlock TextWrapping="Wrap" HorizontalAlignment="Center" Text="{Binding Name}" />
<Button.ContextMenu>
<ContextMenu>
<MenuItem Header="Delete"
Command="{Binding PlacementTarget.Tag.ConnectionRemoveCommand, RelativeSource={RelativeSource AncestorType=ContextMenu}}"
CommandParameter="{Binding}" />
</ContextMenu>
</Button.ContextMenu>
</Button>

Related

Adding Static Button to MenuItem when binded to ItemSouce

i have an observable collection as ItemSource for my menuitems.
i want a simple button (see commented part) at end of menu item list that can add new item to this collection.
it seem simple But it throw a System.Windows.Markup.XamlParseException in my code telling the collection is already in use.
what is the correct way to achieve this?
<Menu Background="Transparent">
<MenuItem Header="WorkSpace" Background="Transparent" ItemsSource="{Binding NosWorkSpaces}">
<ItemsControl.ItemTemplate>
<DataTemplate >
<StackPanel Orientation="Horizontal">
<Label Content="{Binding Original.Title}"></Label>
<Button Content="Select" Tag="WorkSpace_Load" Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=mah:MetroWindow}, Path=DataContext.SelectWorkspaceCommand}" CommandParameter="{Binding }" />
<Button Content="Load" Tag="WorkSpace_Load" Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=mah:MetroWindow}, Path=DataContext.LoadBinaryWorkspace}" CommandParameter="{Binding }" />
<Button Content="Save" Tag="WorkSpace_Save" Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=mah:MetroWindow}, Path=DataContext.SaveWorkspaceCommand}" CommandParameter="{Binding }" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
<!-- <Button Content="New " /> this wont work -->
</MenuItem>
</Menu>
Well i found a solution mixing some answer, even i find it not so easy for a simple menu.
<Menu Height="24" VerticalAlignment="Top">
<Menu.Resources>
<CollectionViewSource Source="{Binding NosWorkSpaces}" x:Key="YourMenuItems"/>
</Menu.Resources>
<MenuItem Header="WorkSpaces" >
<MenuItem.ItemsSource>
<CompositeCollection>
<CollectionContainer Collection="{Binding Source={StaticResource YourMenuItems}}" />
<Separator></Separator>
<MenuItem Header="Add Worspace" />
</CompositeCollection>
</MenuItem.ItemsSource>
<MenuItem.ItemTemplate>
<DataTemplate >
<StackPanel Orientation="Horizontal">
<Label Content="{Binding Original.Title}"></Label>
<Button Content="Select" Tag="WorkSpace_Load" Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=mah:MetroWindow}, Path=DataContext.SelectWorkspaceCommand}" CommandParameter="{Binding }" />
<Button Content="Load" Tag="WorkSpace_Load" Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=mah:MetroWindow}, Path=DataContext.LoadBinaryWorkspace}" CommandParameter="{Binding }" />
<Button Content="Save" Tag="WorkSpace_Save" Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=mah:MetroWindow}, Path=DataContext.SaveWorkspaceCommand}" CommandParameter="{Binding }" />
</StackPanel>
</DataTemplate>
</MenuItem.ItemTemplate>
</MenuItem>
</Menu>
giving a mixed menu with itemSource and datatemplate.

Open context menu by click on the whole line in listbox

In my code I have:
<ListBox Name="Playlists_ListBox">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="0,2" >
<Grid.ContextMenu>
<ContextMenu Name="cm" StaysOpen="true" >
<MenuItem Header="Delete"/>
</ContextMenu>
</Grid.ContextMenu>
<TextBlock Name="Name" Text="{Binding Title}" Foreground="White"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
When I want now open context menu, I must click only on TextBlock. How can I do it to open context menu by click on any part of listbox item - one line in listbox?
Add Context menu for your ListBox so that you'll get context menu wherever you click on Listbox
<ListBox Name="Playlists_ListBox">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="0,2" >
<TextBlock Name="Name" Text="{Binding Title}" Foreground="White"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ContextMenu>
<ContextMenu StaysOpen="True">
<MenuItem Header="Delete"/>
</ContextMenu>
</ListBox.ContextMenu>
</ListBox>

How to get bind to base viewmodel from contextmenu inside treeview?

I'm having trouble getting the selection in a contextMenu to bind to my command EditCommand. The buttons in my tree-view bind to it fine, but in the menu it fails. I have read this is most likely due to the contextMenu being in a different UI tree, but solutions using findAncestor and tags have not worked for me. Is there anyway to do bind and still be able to pass the treeViewItem to the method?
My XAML:
<TreeView Background="Transparent"
Margin="10"
Grid.Column="0" Grid.Row="1"
ItemsSource="{Binding Path=TreeViewItems}">
<TreeView.ItemTemplate >
<HierarchicalDataTemplate DataType="{x:Type model:TreeViewSelection}" ItemsSource="{Binding Configs}" >
<DockPanel HorizontalAlignment="Stretch" Background="Transparent"><!--Transparency allows context click on whole row-->
<DockPanel.ContextMenu>
<ContextMenu DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
<MenuItem
Header="Edit"
Command="{Binding ElementName=userControl, Path=DataContext.EditCommand}"<!--Doesn't work-->
CommandParameter="{Binding}">
<MenuItem.Icon>
<Image Source="../Images/edit.png" />
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
</DockPanel.ContextMenu>
<TextBlock DockPanel.Dock="Left" Text="{Binding Title}" />
<StackPanel DockPanel.Dock="Right"
Orientation="Horizontal"
HorizontalAlignment="Right">
<Button Height="23" Width="23"
Command="{Binding ElementName=userControl, Path=DataContext.EditCommand}"<!--Works-->
CommandParameter="{Binding}"
Style="{DynamicResource ImageNoTextButton}"
inf:AttachedProperties.Image="../Images/edit.png"
inf:AttachedProperties.ImageMouseOver="../Images/editMouseOver.png" />
</StackPanel>
</DockPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
Try this:
<DockPanel HorizontalAlignment="Stretch" Background="Transparent"
Tag="{Binding RelativeSource={RelativeSource AncestorType=UserControl}}">
<DockPanel.ContextMenu>
<ContextMenu>
<MenuItem
Header="Edit"
Command="{Binding Path=PlacementTarget.Tag.DataContext.EditCommand, RelativeSource={RelativeSource AncestorType=ContextMenu}}"
CommandParameter="{Binding}">
<MenuItem.Icon>
<Image Source="../Images/edit.png" />
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
</DockPanel.ContextMenu>
...
</DockPanel>

Checked event isn't fired in checkbox in listbox

Hi i'm creating an checklistbox
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox x:Name="CheckBox" Content="{Binding Path=Info.Name}" IsChecked="{Binding IsChecked,Mode=TwoWay}" Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:MainViewModel}}, Path=SimpleCommand}">
</CheckBox>
<TextBlock Margin="20,0,0,0" Text="{Binding Path=Status}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
but when i check the simplecommand isn't call
SimpleCommand = new RelayCommand(obj => MessageBox.Show("alert"), obj => true);
Use the control name rather than the viewmodel for ancestor type
<CheckBox x:Name="CheckBox"
Content="{Binding Path=Info.Name}"
IsChecked="{Binding IsChecked,Mode=TwoWay}"
Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=SimpleCommand}"/>

Binding event from nested control

I'm writing application in windows phone 8 and have problem with bindings.
Here is my xaml code with my page structure
<phone:Pivot Grid.Row="1" SelectedIndex="{Binding SelectedPivotElement, Mode=TwoWay}" x:Name="SymbolsPivot" Title="Symbols" ItemsSource="{Binding CategoriesWithSymbols}">
<phone:Pivot.HeaderTemplate>
<DataTemplate>
<ContentControl Content="{Binding Name}"/>
</DataTemplate>
</phone:Pivot.HeaderTemplate>
<phone:Pivot.ItemTemplate>
<DataTemplate>
<telerikData:RadJumpList x:Name="SymbolsControl" ItemsSource="{Binding Path=Symbols}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
<telerikData:RadJumpList.GroupDescriptors>
<data:PropertyGroupDescriptor PropertyName="GroupName"
SortMode="Ascending" />
</telerikData:RadJumpList.GroupDescriptors>
<telerikPrimitives:RadDataBoundListBox.VirtualizationStrategyDefinition>
<telerikPrimitives:WrapVirtualizationStrategyDefinition Orientation="Horizontal"/>
</telerikPrimitives:RadDataBoundListBox.VirtualizationStrategyDefinition>
<telerikData:RadJumpList.GroupHeaderTemplate>
<DataTemplate>
<Grid Margin="0,-8,0,12" Width="480">
<TextBlock FontWeight="Bold" FontSize="{StaticResource PhoneFontSizeMedium}" Text="{Binding}" TextWrapping="Wrap"/>
</Grid>
</DataTemplate>
</telerikData:RadJumpList.GroupHeaderTemplate>
<telerikData:RadJumpList.ItemTemplate>
<DataTemplate>
<Grid Width="300">
<TextBlock Text="{Binding Symbol}"/>
</Grid>
</DataTemplate>
</telerikData:RadJumpList.ItemTemplate>
</telerikData:RadJumpList>
</DataTemplate>
</phone:Pivot.ItemTemplate>
</phone:Pivot>
<i:Interaction.Triggers>
<i:EventTrigger EventName="ItemTap" SourceName="SymbolsControl" >
<cmd:EventToCommand Command="{Binding TapCommand}"
/>
</i:EventTrigger>
</i:Interaction.Triggers>
So I have pivot control and inside pivot I have a list.
And now the problem is that application binds item tap event to my relay command but this event/command is never called. Everything works if I move list outside pivot. How to fix that problem ?

Categories

Resources