Binding ContextMenu Items - wpf

I have a treeView with some ContextMenu.
One of the ContextMenu items is a "Add Item" menu Item. this item sholud holds as child list of items, where this list is binded to some ObervableCollcetion.
Each model has "Header" and "IsEnabled". each item in the list add as new MenuItem.
My problem is that only after the first time , all items get the proper IsEnabled value.
when I changing some model data, it doean't changes the visisbiltiy of the meneItem.
I'm sure that there is no bug in the ObervableCollcetion because I also use it in other view and its acts properly.
here is the code:
<TreeView Name="tvSceneTree" ItemsSource="{Binding Converter={StaticResource mlControlSceneTreeVMConverter}}"
Height="auto" AllowDrop="True" SelectedItemChanged="tvSceneTree_SelectedItemChanged">
<TreeView.ContextMenu>
<ContextMenu Name="mainContextMenu" Opened="mainContextMenu_Opened">
<MenuItem Header="Add Item" Name="addItemMenu" ItemsSource="{Binding Path=ControlBoxItems}">
<MenuItem.ItemTemplate>
<DataTemplate>
<MenuItem Header="{Binding ControlName}" IsEnabled ="{Binding IsEnabled}"
Command="{Binding Source={x:Static ev:ApplicationCommands.AddControlToScene}}" CommandParameter="{Binding}"/>
</DataTemplate>
</MenuItem.ItemTemplate>
</MenuItem>
<MenuItem Header="Copy" Command="{Binding Source={x:Static ev:ApplicationCommands.Copy}}" />
<MenuItem Header="Paste" Command="{Binding Source={x:Static ev:ApplicationCommands.Paste}}" />
<MenuItem Header="Cut" Command="{Binding Source={x:Static ev:ApplicationCommands.Cut}}" />
<MenuItem Header="Duplicate" IsEnabled="{Binding Path=ControlItem, Converter={StaticResource canDoActionOnControlConverter}, ConverterParameter=CanBeDuplicated}" Command="{Binding Source={x:Static ev:ApplicationCommands.DuplicateControl}}" CommandParameter="{Binding}" />
<MenuItem Header="Delete" IsEnabled="{Binding Path=ControlItem, Converter={StaticResource canDoActionOnControlConverter}, ConverterParameter=CanBeRemove}" Command="{Binding Source={x:Static ev:ApplicationCommands.DeleteControl}}" CommandParameter="{Binding}" />
<MenuItem Header="Add animation" IsEnabled="{Binding Path=ControlItem.AnimationStubs,Converter={StaticResource collectionCountToBoolConverter}}" Command="{Binding Source={x:Static ev:ApplicationCommands.AddAnimation}}" CommandParameter="{Binding}" />
<!--<MenuItem Header="Rename" Command="{Binding Source={x:Static ev:ApplicationCommands.RenameControl}}" CommandParameter="{Binding}" />-->
</ContextMenu>
</TreeView.ContextMenu>

Related

i need to bind the context menu with the tag , but this code didnt work for me

i need to bind the context menu with the tag , but this code didnt work for me.
<TextBox Width="100" Name="dd" Tag="jatin" Height="50" Text="{Binding Tag, RelativeSource={RelativeSource Self}}">
<TextBox.ContextMenu>
<ContextMenu>
<MenuItem Header="harsh"></MenuItem>
<MenuItem Header="jatin"></MenuItem>
<MenuItem Header="{Binding Path=Tag,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=Grid},FallbackValue=BindingFailed}"></MenuItem>
</ContextMenu>
</TextBox.ContextMenu>
</TextBox>
</Grid>
Try this,
<MenuItem Header="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource AncestorType=ContextMenu}}" />

Create separate context menu for listview and for listview item

I have working context menu for listview control in my WPF app. I'd like to have context menu items enabled if user right clicks on listview item but disabled them is click occurs on panel area of listview.
Thanks
MK
Update: this is the my list view that works but I'd like to disable MenuItems "Remove" and "Calculate" when user clicks on panel area. Thanks for responding
<ListView Name="lb_proplist" DisplayMemberPath ="Name" HorizontalAlignment="Left" ToolTip="Use right click to see more options"
ItemsSource="{Binding Converter={StaticResource FilterByPropTypeConverter}}" Margin="0,0,0,0"
ContextMenuOpening="ContextMenu_ContextMenuOpening" >
<ListView.ContextMenu>
<ContextMenu >
<MenuItem Name="cmi_addNew" Header="Add New"
Command="{Binding AddNewItemItem}"
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=ContextMenu}}" />
<MenuItem Name="cmi_remove" Header="Remove"
Command="{Binding RemoveItem}"
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=ContextMenu},
Path=PlacementTarget.SelectedItem}" />
<MenuItem Name="cmi_calculate" Header="Calculate"
Command="{Binding CalculateItem}"
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=ContextMenu},
Path=PlacementTarget.SelectedItem}" />
</ContextMenu>
</ListView.ContextMenu>
<ListView.View>
<GridView>
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}" Width="200"/>
</GridView>
</ListView.View>
</ListView>
Well, this can be done using ItemsTemplate property for ListView:
<ListView.ItemTemplate>
<DataTemplate>
<DockPanel Tag = "{Binding DataContext, ElementName=myListView}">
<TextBlock Text="{Binding}"/>
<DockPanel.ContextMenu>
<ContextMenu>
<MenuItem Header="Local Item 1"
Command="{Binding Path=PlacementTarget.Tag.CommandName, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}"/>
<MenuItem Header="Local Item 2"/>
</ContextMenu>
</DockPanel.ContextMenu>
</DockPanel>
</DataTemplate>
</ListView.ItemTemplate>
In example, ContextMenu is created only for items, but not for whole control.
Also, Tag is added into DockPanel to access original DataContext.
Well, in case of GridView you need to override style for ListViewItem, and bind ContextMenu as StaticResource.
<ListView.Resources>
<ContextMenu x:Key="ItemContextMenu">
<MenuItem Header="Add New"/>
</ContextMenu>
</ListView.Resources>
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="ContextMenu" Value="{StaticResource ItemContextMenu}"/>
</Style>
</ListView.ItemContainerStyle>
Please, take a look at this article and answer.

CommandParameter with MVVM Light

I'm trying to get a RelayCommand working with a CommandParameter working using MVVM Light. The command is defined in my viewmodel, and I want to pass the selected ListBox item as the parameter. The command is bound, but the parameter is not. Is this possible?
<UserControl x:Class="Nuggets.Metro.Views.EmployeeListView"
...
DataContext="{Binding EmployeeList,Source={StaticResource Locator}}">
<ListBox x:Name="lstEmployee" ItemsSource="{Binding EmployeeItems}" Style="{StaticResource EmployeeList}" Tag="{Binding EmployeeItems}">
<ListBox.ContextMenu>
<ContextMenu DataContext="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
<MenuItem Header="Edit item" Command="{Binding EditEmployeeCommand}" CommandParameter="{Binding PlacementTarget.SelectedItem,RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}"/>
<MenuItem Header="Delete item" Command="{Binding DeleteEmployeeCommand}" CommandParameter="{Binding PlacementTarget.SelectedItem,RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}"/>
</ContextMenu>
</ListBox.ContextMenu>
This should work
<ContextMenu DataContext="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
<MenuItem Header="Edit item"
Command="{Binding EditEmployeeCommand}"
CommandParameter="{Binding SelectedItem,ElementName=lstEmployee}"/>
<MenuItem Header="Delete item"
Command="{Binding DeleteEmployeeCommand}"
CommandParameter="{Binding SelectedItem,ElementName=lstEmployee}"/>
</ContextMenu>
Use the Name of your ListBox als ElementName in the binding of the CommandParameter and set the path to SelectedItem.
Update:
The above code does not work for ListBox and ContextMenu, cause they belong to diffrent visual trees. The result is
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'ElementName=lstEmployee'. BindingExpression:Path=SelectedItem; DataItem=null; target element is 'MenuItem' (Name=''); target property is 'CommandParameter' (type 'Object')
The following XAML does the job. Using the PlacementTarget (that is the ListBox) of the ContextMenu.
<ContextMenu DataContext="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
<MenuItem Header="Edit item"
Command="{Binding EditEmployeeCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=ContextMenu}, Path=PlacementTarget.SelectedItem}"/>
<MenuItem Header="Delete item"
Command="{Binding DeleteEmployeeCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=ContextMenu}, Path=PlacementTarget.SelectedItem}"/>
</ContextMenu>
This works for TreeView or ListView with MVVM.
The PlacementTarget from the ContextMenu is (here) the Listview
<ListView.ContextMenu>
<ContextMenu>
<MenuItem x:Name="OpenExplorer"Header="ShowFolder"
Command="{Binding ShowExplorer}"
CommandParameter ="{Binding Path=PlacementTarget.SelectedItem,
RelativeSource={RelativeSource AncestorType=ContextMenu}}"/>
</ContextMenu>
</ListView.ContextMenu>

WPF Datagrid dgDataGrid_Loaded event triggers more than once

I have a wpf dadatagrid and every time the contents being loaded the dgDataGrid_Loaded event triggers twice.
I am not sure whether this is WPF bug or I have missed something!?
here is my Xaml code:
<my:DataGrid Name="dgDataGrid" DockPanel.Dock="Top"
AutoGenerateColumns="False" ClipboardCopyMode="ExcludeHeader"
CanUserDeleteRows="True"
SelectionMode="Extended" SelectionUnit="FullRow"
FontFamily="Tahoma"
ItemsSource="{Binding}"
VirtualizingStackPanel.VirtualizationMode="Recycling"
VirtualizingStackPanel.IsVirtualizing="True"
EnableRowVirtualization="false"
EnableColumnVirtualization="False"
IsSynchronizedWithCurrentItem="True"
BorderBrush="Blue"
RowBackground="White"
HorizontalGridLinesBrush="Blue"
GridLinesVisibility="Horizontal" VerticalGridLinesBrush="Blue" IsTextSearchEnabled="False"
IsTabStop="True" HeadersVisibility="All"
Loaded="dgDataGrid_Loaded" ContextMenuOpening="dgDataGrid_ContextMenuOpening"
LoadingRow="dgDataGrid_LoadingRow">
<my:DataGrid.Resources>
</my:DataGrid.Resources>
<my:DataGrid.RowHeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type my:DataGridRow}}, Path=Header}"></TextBlock>
</DataTemplate>
</my:DataGrid.RowHeaderTemplate>
<my:DataGrid.ColumnHeaderStyle>
<Style TargetType="my:DataGridColumnHeader">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="{Binding}" Foreground="Blue"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</my:DataGrid.ColumnHeaderStyle>
<my:DataGrid.ContextMenu>
<ContextMenu Name="cmDataGrid" StaysOpen="True">
<MenuItem Name="mnuView" Header="نمایش">
<MenuItem Name="mnuHideColumn" Header="Hide Column" Click="mnuHideColumn_Click"/>
<MenuItem Name="mnuShowColumn" Header="Show Column"/>
<Separator/>
<MenuItem Name="mnuGroupByColumn"
Header="Group by this column" Click="mnuGroupColumn_Click" />
<MenuItem Name="mnuClearGroups"
Header="Clear grouping" Click="mnuGroupColumn_Click" />
<Separator/>
<MenuItem Header="Header Alignment">
<MenuItem Name="mnuHeaderCenter" Header="Center"/>
<MenuItem Name="mnuHeaderLeft" Header="Left"/>
<MenuItem Name="mnuHeaderRight" Header="Right"/>
</MenuItem>
<MenuItem Header="Content Alignment">
<MenuItem Name="mnuContentCenter" Header="Center"/>
<MenuItem Name="mnuContentLeft" Header="Left"/>
<MenuItem Name="mnuContentRight" Header="Right"/>
</MenuItem>
</MenuItem>
</ContextMenu>
</my:DataGrid.ContextMenu>
</my:DataGrid>
Any suggestions?

WPF contextmenu binding

Cant seem to bind a menuitem in my contextmenu to a command in my viewmodel. I know the contextmenu does not live in the visual tree. For testing purposes i have bound to the same command twice in a button. The first binding works but i can get the second binding in the contextmenu to bind. I can see the binding error in output. Someone has any idea?
<HierarchicalDataTemplate DataType="{x:Type inf:OSiteEquipment}" ItemsSource="{Binding Path=SubSystems, Converter={StaticResource subsystemConverter}}" >
<Button HorizontalContentAlignment="Left"
Command="{Binding DataContext.CommandOpenSelected, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}}"
CommandParameter="{Binding}">
<TextBlock Text="{Binding Path=PartData.Name}" TextTrimming="CharacterEllipsis" />
<Button.ContextMenu>
<ContextMenu>
<MenuItem Header="Add Category" Command="{Binding Path=Parent.PlacementTarget.Tag.CommandOpenSelected, RelativeSource={RelativeSource AncestorType=ContextMenu}}" />
</ContextMenu>
</Button.ContextMenu>
</Button>
</HierarchicalDataTemplate>
Just remove the "Parent" in the Databinding path :
<HierarchicalDataTemplate DataType="{x:Type inf:OSiteEquipment}" ItemsSource="{Binding Path=SubSystems, Converter={StaticResource subsystemConverter}}" >
<Button HorizontalContentAlignment="Left"
Command="{Binding DataContext.CommandOpenSelected, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}}"
CommandParameter="{Binding}">
<TextBlock Text="{Binding Path=PartData.Name}" TextTrimming="CharacterEllipsis" />
<Button.ContextMenu>
<ContextMenu>
<MenuItem Header="Add Category" Command="{Binding Path=PlacementTarget.Command, RelativeSource={RelativeSource AncestorType=ContextMenu}}" />
</ContextMenu>
</Button.ContextMenu>
</Button>
</HierarchicalDataTemplate>
You already find the Parent via the relative source -> Omit the Parent in the path
You did not even set the Tag on the PlacementTarget (Button) -> Set it respectively

Resources