Click here to Skip to main content
15,888,286 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hello,
I have a WPF application which displays list of items (listview).
The context menu is added as a resource to the listview:
HTML
<listview.resources>
                <contextmenu x:key="ItemContextMenu" opened="listViewContextMenu_Opened" contextmenuopening="listViewContextMenu_ContextMenuOpening" name="listViewContextMenu" xmlns:x="#unknown">
                    <menuitem header="Rename" previewmousedown="RenameMenuItem_MouseDown" />
                    <menuitem header="Delete" previewmousedown="DeleteMenuItem_MouseDown" />
                    <menuitem header="View File" previewmousedown="ViewFileMenuItem_PreviewMouseDown" />
                </contextmenu>
            </listview.resources>


And then used in an item container style:

HTML
<listview.itemcontainerstyle>
                <Style TargetType="{x:Type ListViewItem}">
                    <eventsetter event="PreviewMouseLeftButtonDown" handler="OnListViewItem_PreviewMouseButtonDown" />
                    <setter property="ContextMenu" value="{StaticResource ItemContextMenu}" />
                </Style>
            </listview.itemcontainerstyle>


Now, the problem is I want to prevent some context menu items based on the line selected, i.e, I need to analize the item selected and then decide which items to display.

I couldn't find a way to do that, please help!
Posted

1 solution

Hi,

this could be accomplished with binding. Use the following:

C# - ViewModels:
C#
public class ListViewViewModel : INotifyPropertyChanged
   {
      public event PropertyChangedEventHandler PropertyChanged;

      public List<ItemViewModel> ItemsSource
      {
         get;
         set;
      }

      public ListViewViewModel()
      {
         this.ItemsSource = new List<ItemViewModel>();
         this.ItemsSource.Add(new ItemViewModel
         {
            DisplayText = "ItemsSource #1"
         });
         this.ItemsSource.Add(new ItemViewModel
         {
            DisplayText = "ItemsSource #2"
         });
         this.ItemsSource.Add(new ItemViewModel
         {
            DisplayText = "ItemsSource #3"
         });
      }
   }
C#
public class ItemViewModel : INotifyPropertyChanged
{
   public event PropertyChangedEventHandler PropertyChanged;

   public string DisplayText { get; set; }

   public Visibility M1Visibility {
      get {
         return (!this.DisplayText.Contains("1")) ? Visibility.Visible : Visibility.Collapsed;
      }
   }

   public Visibility M2Visibility {
      get {
         return (!this.DisplayText.Contains("2")) ? Visibility.Visible : Visibility.Collapsed;
      }
   }
}

XAML:
HTML
<ListView
   ItemsSource="{Binding Path=ItemsSource}" DisplayMemberPath="DisplayText">
   <ListView.ItemContainerStyle>
      <Style
         TargetType="{x:Type ListViewItem}">
         <Setter
            Property="ContextMenu">
            <Setter.Value>
               <ContextMenu>
                  <MenuItem
                     Header="MenueItem #1"
                     Visibility="{Binding Path=M1Visibility}" />
                  <MenuItem
                     Header="MenueItem #2"
                     Visibility="{Binding Path=M2Visibility}" />
               </ContextMenu>
            </Setter.Value>
         </Setter>

      </Style>
   </ListView.ItemContainerStyle>

</ListView>

I've made a few changes to your XAML for the sake clearness (this was at least my intention). There is a line of code missing, where the DataContext of the ListView's container is set to an instance of ListViewViewModel.

If you use this, you will see, that the ListItem #1 hides MenueItem #1, ListItem #2 hides MenueItem #2 and the last ListItem hides no MenueItem.

The key concept is, that the DataContext for the ContextMenue is inherited from the ListViewItem; so it is the point where to apply the visbility-logic. You can use some context-specific logic as I did or you can use the initialisers to provide the visibility values.

If you need further help, feel free to ask.

Cheers
Jürgen

--
If this saved you some time, please spend a bit of it to vote.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900