2017-02-12 21 views
0

У меня вопрос с двумя частями, я надеюсь, что нормально спросить их обоих сразу.WPF: Как управлять всплывающим контекстом меню в виде списка/gridview

У меня есть WPF ListView с изображением GridView.

Некоторое время назад я искал способ получить ContextMenu в ListView, который появляется только тогда, когда пользователь нажимает на фактический элемент ListView.

Все решения, которые я нашел в Интернете, предложили поместить это ContextMenu внутри ItemContainerStyle, поэтому я сделал это, и он работает.

1. Вопрос, общий один

Но теперь это заставило меня задуматься ... если мой ListView содержит тысячи пунктов, это значит я создал тысячи одинаковых ContextMenu с в памяти, а? И если бы я сделал, нет ли лучшего способа получить один item ContextMenu?

2. вопрос, конкретный один (устаревшее см EDIT ниже)

Теперь я стараюсь, чтобы получить другой ContextMenu всплывал, когда пользователь нажимает на право на GridView сек заголовка, и снова все решения предлагают положить его в GridViewColumnHeader.

У меня есть две проблемы с этим. Во-первых, он снова создает одинаковые ContextMenu s для каждого из столбцов, а во-вторых, появляется только сообщение ContextMenu, когда пользователь щелкает правой кнопкой мыши на один из заголовков столбцов. Когда в области заголовка есть свободное пространство (поскольку для всех столбцов не требуется все свободное пространство), ContextMenu не появится при щелчке правой кнопкой мыши на свободном пространстве области заголовка.

Есть ли способ всплыть одинContextMenu, когда правый щелчок по области заголовка GridView?

Я бы предпочел, чтобы решение было только в XAML, если это возможно.

Благодарим за помощь.

EDIT:

Пожалуйста, забудьте вторую часть вопроса. Я нашел свойство ColumnHeaderContextMenuGridView, которое точно выполняет то, что я искал.

ответ

1

Примем следующие пользовательские элементы управления:

public class MTextBlock : TextBlock 
{ 
    public MTextBlock() 
    {// breakpoint 

    } 
} 
public class MContextMenu : ContextMenu 
{ 
    public MContextMenu() 
    {// breakpoint 

    } 
} 

И следующий ItemsControl в Xaml:

<ItemsControl Name="ic" ItemTemplate="{StaticResource res}"/> 

, в котором ItemsSource будут установлены в коде позади.

Если вы используете следующие настройки

<DataTemplate x:Key="res"> 
     <TextBlock Text="A a a a a "> 
      <TextBlock.ContextMenu> 
       <local:MContextMenu> 
        <MenuItem Header="Item1"> 
         <local:MTextBlock Text="u" /> 
        </MenuItem> 
       </local:MContextMenu> 
      </TextBlock.ContextMenu> 
     </TextBlock> 
    </DataTemplate> 

несколько экземпляров MContextMenu и MTextBox будет сгенерирован. Вы можете проверить это, установив точки останова на конструкторах.

Однако, если вы объявите контроль как статический ресурс, например:

<Window.Resources> 
    <local:MContextMenu x:Key="cm"> 
     <MenuItem Header="Item1"> 
      <local:MTextBox Text="u" /> 
     </MenuItem> 
    </local:MContextMenu> 
    <DataTemplate x:Key="res"> 
     <TextBlock Text="{Binding Path=Name}" Background="Transparent" Width="100" ContextMenu="{StaticResource cm}"> 
     </TextBlock> 
    </DataTemplate> 
</Window.Resources> 

только будет создан один экземпляр из них. Снова проверьте его, установив правильные точки останова. Обратите внимание, что в этом случае, если вы измените свойство Text объекта MTextBox, это влияет на все _MTextBox_es в разных _ContextMenu_s.

+0

И можно ли создать это контекстное меню только для всех элементов? – Nostromo

+0

см. Редактирование. Набор является статическим ресурсом, и он будет создан только один раз. – Ron

1

если мой ListView содержит тысячи пунктов, это означает, что я создал тысячи идентичных ContextMenus в памяти, а?

No.

Вы можете подтвердить это, создав свой собственный тип ContextMenu, установить точку останова в конструкторе и отладки приложения:

Public Class MyContextMenu 
    Inherits ContextMenu 

    Public Sub New() 
     Items.Add(New MenuItem() With {.Header = "1"}) 
     Items.Add(New MenuItem() With {.Header = "2"}) 
     Items.Add(New MenuItem() With {.Header = "3"}) 
    End Sub 

End Class 

<ListView x:Name="listView1"> 
    <ListView.Resources> 
     <local:MyContextMenu x:Key="cm" /> 
    </ListView.Resources> 
    <ListView.ItemContainerStyle> 
     <Style TargetType="ListViewItem"> 
      <Setter Property="ContextMenu" Value="{StaticResource cm}" /> 
     </Style> 
    </ListView.ItemContainerStyle> 
</ListView> 

данную контрольную точку не будет ударяться один раз за каждый элемент, который вы добавите в коллекцию ItemsListView, так что не беспокоиться об этом.

И это не имеет значения, является ли свойство устанавливается с помощью StaticResource:

<ListView.ItemContainerStyle> 
    <Style TargetType="ListViewItem"> 
     <Setter Property="ContextMenu"> 
      <Setter.Value> 
       <local:MyContextMenu /> 
      </Setter.Value> 
     </Setter> 
    </Style> 
</ListView.ItemContainerStyle> 

Установки ContextMenu свойство ItemContainerStyle является правильным способом ассоциирования контекстного меню с ListViewItem контейнером.