2017-10-14 47 views
0

考慮一個ListBox,在運行時可能不會完全用ListBoxItems填充。我想爲該ListBox自定義ContextMenu,具體取決於用戶是否右鍵單擊其中一個ListBoxItem或沒有項目存在的空白區域。如何爲wpf列表框自定義ContextMenu

我遇到的問題是,在後一種情況下,不會觸發ListBox事件,只會觸發ContextMenuOpening事件。從那個事件我不知道如何確定用戶是否右鍵單擊現有的ListBoxItem或不。

我已經看過所有的ListBox屬性和事件,但canot想出了一種方法來區分這兩種情況。我曾考慮過使用樣式觸發器,但是,核心問題是空白區域的右鍵單擊不會觸發任何ListBox事件。我也回顧了SO建議的鏈接,但沒有人會提到這個問題。

這怎麼辦?

+0

請給出一些代碼來解釋你的問題更清楚嗎? – Iron

+0

你能展示你使用的邏輯以及你的邏輯與哪些事件相連接嗎?您可以在資源中創建兩個ContextMenu,並在ListBox.ContextMenu和ListBoxItem.ContextMenu中使用它們。 – Redouane

+0

@Iron它不是一個編碼問題,而是一個概念性問題:如何檢測在部分填充的列表框中點擊右鍵單擊的內容。如果我有任何代碼,我會顯示它。但請參閱下面的解決方案。 – SezMe

回答

0

我設計了一個解決方案,但並不漂亮,但工作。基本上,只要在列表框失去焦點,我強迫它什麼都沒有通過設置選擇現在

ListBox.SelectedIndex = -1 

,在事件的ContextMenuOpening當焦點返回到列表框,就可以得到得到ListBox.SelectedIndex如果它是-1,那麼用戶點擊ListBox的空白部分,否則點擊一個ListBoxItem。

編碼這個邏輯很簡單。

0

也許我還不知道你的意圖:您可以定義不同ContextMenu無論是在XAMLCode-behind這樣的:

XAML:

<ListBox PreviewMouseDown="ListBox_PreviewMouseDown"> 
    <ListBox.ItemContainerStyle> 
     <Style TargetType="{x:Type ListBoxItem}"> 
      <Setter Property="Template"> 
       <Setter.Value> 
        <ControlTemplate TargetType="{x:Type ListBoxItem}"> 
         <ContentPresenter> 
          <ContentPresenter.ContextMenu> 
           <ContextMenu> 
            <MenuItem Header="ListBoxItem"></MenuItem> 
            <MenuItem Header="ListBoxItem"></MenuItem> 
            <MenuItem Header="ListBoxItem"></MenuItem> 
           </ContextMenu> 
          </ContentPresenter.ContextMenu> 
         </ContentPresenter> 
        </ControlTemplate> 
       </Setter.Value> 
      </Setter> 
     </Style> 
    </ListBox.ItemContainerStyle> 
    <ListBoxItem>Item1</ListBoxItem> 
    <ListBoxItem>Item2</ListBoxItem> 
    <ListBoxItem>Item2</ListBoxItem> 
    <ListBoxItem>Item2</ListBoxItem> 
    <ListBox.ContextMenu> 
     <ContextMenu> 
      <MenuItem Header="ListBox"></MenuItem> 
      <MenuItem Header="ListBox"></MenuItem> 
      <MenuItem Header="ListBox"></MenuItem> 
     </ContextMenu> 
    </ListBox.ContextMenu> 
</ListBox> 

代碼隱藏:

private void ListBox_PreviewMouseDown(object sender, MouseButtonEventArgs e) 
{ 
    if(e.ChangedButton == MouseButton.Right) 
    { 
     var listBoxItem = e.Source as ListBoxItem; 
     if (listBoxItem != null) 
     { 
      // clicked on ListBoxItem, customize the ContextMenu 
     } 

     var listBox = e.Source as ListBox; 
     if (listBox != null) 
     { 
      // clicked on ListBox, customize the ContextMenu 
     } 
    } 
} 
0

下面是一個更簡潔的方法來定義ListBox和的兩個不同的,無需任何代碼隱藏檢查,它就像一個魅力:

<ListBox ContextMenu="{StaticResource ListContextMenu}"> 
    <ListBox.Resources> 
     <!-- Context Menu when right click on selected List Item --> 
     <ContextMenu x:Key="ItemContextMenu"> 
      <MenuItem Header="Eat"></MenuItem> 
      <MenuItem Header="Delete"></MenuItem> 
      <Separator></Separator> 
      <MenuItem Header="Send To Friend"></MenuItem> 
     </ContextMenu> 
     <!-- Context Menu when right click on listbox space --> 
     <ContextMenu x:Key="ListContextMenu"> 
      <MenuItem Header="Save Fruits"></MenuItem> 
      <MenuItem Header="Add Or Remove Fruits"></MenuItem> 
     </ContextMenu> 
     <!-- Applying Context Menu to ListBoxItem with Style --> 
     <Style TargetType="{x:Type ListBoxItem}"> 
      <Setter Property="ContextMenu" Value="{StaticResource ItemContextMenu}"> 
      </Setter> 
     </Style> 
    </ListBox.Resources> 

    <ListBox.ContextMenu> 
     <Binding Source="{StaticResource ListContextMenu}"></Binding> 
    </ListBox.ContextMenu> 


    <ListBoxItem>Banana</ListBoxItem> 
    <ListBoxItem>Apple</ListBoxItem> 
    <ListBoxItem>Orange</ListBoxItem> 
</ListBox> 

如果你想修改動態地根據所選項目的ListBoxItem.ContextMenu內容,你可以掛鉤的處理程序ContextMenu.Opened事件,並在處理程序檢查所選項目並在代碼中將新的MenuItem集合添加到您的ContextMenu

請注意,這兩個ContextMenu將僅在此ListBox內顯示,因爲它們在其​​中定義。