Хобрук: Ваш путь к мастерству в программировании

Поиск того, что было выбрано в списке со списком, с помощью щелчка правой кнопкой мыши

Я пишу настольное приложение для Windows, используя C # и WPF. У меня есть поле со списком, которое используется либо для ввода пути к файлу, либо для выбора из ранее использованных путей к файлам. Файлы в списке могут стать недействительными, если файл был удален или пользователь ввел действительный файл, но не нужный файл. Они попросили способ удалить плохие записи из раскрывающегося списка поля со списком. Они хотят щелкнуть элемент правой кнопкой мыши и выбрать в контекстном меню команду «Удалить».

<ComboBox x:Name="cbDocket" IsEditable="True">
   <ComboBox.ContextMenu>
        <ContextMenu>
            <MenuItem Header="Remove" Click="cbDocket_MenuItemRemove">/>
        </ContextMenu>
    </ComboBox.ContextMenu>
</ComboBo>

Это легкая часть. Я не могу понять, как определить, какой элемент они выбрали. Поиск не нашел подходящих предложений. Любая помощь будет оценена. Есть ли другой способ сделать это проще? О да, я новичок как в C #, так и в WPF.

Спасибо, Брайан

17.05.2016

Ответы:


1

Контекстные меню в WPF довольно сильно разбиты по дизайну, поэтому примерно в половине всех обычных случаев все, что вы делаете, что действительно работает, является кладжем. Я придумал несколько; вот еще один, который на самом деле не такой уж и беспорядочный.

XAML:

<ComboBox x:Name="cbDocket" IsEditable="True">
    <ComboBox.Resources>
        <ContextMenu x:Key="ItemMenu">
            <MenuItem Header="Remove" Click="MenuItem_Click" />
        </ContextMenu>
    </ComboBox.Resources>

    <!-- Some arbitrary random junk to display in the ComboBox -->
    <TextBlock Text="Foo" />
    <TextBlock Text="Bar" />
    <!-- End of arbitrary random junk -->

    <ComboBox.ItemContainerStyle>
        <Style TargetType="{x:Type ComboBoxItem}">
            <Setter 
                Property="ContextMenu" 
                Value="{StaticResource ItemMenu}" 
                />
        </Style>
    </ComboBox.ItemContainerStyle>
</ComboBox>

Код позади:

private void MenuItem_Click(object sender, RoutedEventArgs e)
{
    //  This needs some null checking and a try catch, but this is the guts of it. 

    //  sender should be the MenuItem as well
    var menuItem = e.OriginalSource as MenuItem;

    //  Since we used ItemContainerStyle to give each ComboBoxItem its own 
    //  personal ContextMenu, each ContextMenu will have its PlacementTarget
    //  set to the ComboBoxItem that owns it. 
    var cbItem = (menuItem.Parent as ContextMenu).PlacementTarget as ComboBoxItem;

    //  ???
    //var dataItem = cbItem.DataContext;
}

Вы не упомянули, как вы заполняете поле со списком, поэтому я не знаю, установлены ли у вас DataContext элементы или что-то еще. Но как только у вас будет ComboBoxItem, вы сможете туда добраться.

17.05.2016
  • Оно работает! Поле заполняется тем, что вводит пользователь, или кнопкой выбора с помощью OpenFileDialog. Не знаю о DataContext. Это предварительная тема, которую я еще не изучил. 17.05.2016

  • 2

    Добавьте событие для отслеживания движения мыши при открытом раскрывающемся списке и используйте его при нажатии кнопки удаления.

        <ComboBox x:Name="cbDocket" HorizontalAlignment="Left" Margin="33,30,0,269" Width="124" IsEditable="True">
            <ComboBox.ContextMenu>
                <ContextMenu Name="Menu">
                    <MenuItem Header="Remove" Click="cbDocket_MenuItemRemove"/>
                </ContextMenu>
            </ComboBox.ContextMenu>
            <ComboBox.ItemContainerStyle>
                <Style TargetType="{x:Type ComboBoxItem}">
                    <EventSetter Event="MouseMove" Handler="cbDocket_OnMouseMove" />
                </Style>
            </ComboBox.ItemContainerStyle> 
    </ComboBox>
    

    Код позади:

    ComboBoxItem cbiSelected = null;
    
    private void cbDocket_MenuItemRemove(object sender, RoutedEventArgs e)
    {
        cbDocket.Items.Remove(cbiSelected);
    }
    
    private void cbDocket_OnMouseMove(object sender, MouseEventArgs e)
    {
        ComboBoxItem cbiHover = sender as ComboBoxItem;
        if (cbiHover.IsHighlighted)
        {//Verify the item is highlighted
            cbiSelected = cbiHover;
        }
    }
    
    17.05.2016

    3

    Есть несколько способов сделать это. Поскольку вы используете обработчик событий Click, то source события всегда является элементом, по которому был выполнен щелчок. Например:

    Xaml:

    <ComboBox x:Name="cbDocket" IsEditable="True">
        <ComboBox.ContextMenu>
            <ContextMenu>
                <MenuItem Header="Remove" Click="cbDocket_MenuItemRemove">/>
            </ContextMenu>
        </ComboBox.ContextMenu>
    </ComboBo>
    

    Xaml.cs:

    private void cbDocket_MenuItemRemove(object source, EventArgs args)
    {
        // Source is your item:
        cbDocekt.Items.Remove(cbDocket.SelectedItem);
    }
    

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

    Я предполагаю, что вы используете для этого код.

    17.05.2016
  • Когда я пробую это, я обнаруживаю, что source - это MenuItem, а ((source as MenuItem).Parent as ContextMenu).PlacementTarget - это ComboBox. Разве это не то, что вы видели, когда тестировали? 17.05.2016
  • source - это MenuItem, чего я ожидал из приведенного примера кода. ComboBox было дано имя: cbDocket в исходном коде. Таким образом, OP может пройти путь, который вы выбрали, чтобы добраться до ComboBox, или просто получить к нему прямой доступ. Есть еще больше способов снять шкуру с этой кошки, но я решил сделать это как можно ближе к предоставленному коду. 17.05.2016
  • Вернувшись к своему ответу и рассмотрев его более подробно, я упустил важную деталь: OP хотел удалить выбранный элемент. Это был действительно долгий день ... 17.05.2016
  • Я считал, что он хотел, чтобы они могли нажимать на произвольные элементы в раскрывающемся списке, а не только на выбранный элемент. На самом деле я должен проверить, работает ли мой ответ для выбранного элемента ... 17.05.2016
  • Упс. Это редактируемое поле со списком; щелкнув по нему, когда он закрыт, вы, конечно же, получите контекстное меню TextBox 17.05.2016
  • У меня самого в последнее время было несколько долгих дней. Ваше здоровье! 17.05.2016
  • Правильный. Я хочу, чтобы пользователь мог навести курсор на любой элемент в раскрывающемся списке, щелкнуть правой кнопкой мыши и выбрать «Удалить». Затем этот элемент удаляется из списка. Ответ Эда, кажется, работает. Спасибо! 17.05.2016

  • 4

    С помощью следующего программного кода вы можете добавить контекстное меню в поле со списком. В этом контекстном меню можно удалить один элемент или все элементы поля со списком.

    Поле со списком с контекстным меню

    private ComboBox FolderComboBox;
    private ContextMenu FolderHistoryContextMenu;
    
    ...    
    
    private void CreateFolderHistoryContextMenu()
    {
      MenuItem RemoveFolderMenuItem, RemoveAllFoldersMenuItem;
    
      FolderHistoryContextMenu = new ContextMenu();
      RemoveFolderMenuItem = new MenuItem();
      RemoveFolderMenuItem.Header = "Remove folder";
      RemoveFolderMenuItem.Click += new RoutedEventHandler(RemoveFolderMenuItem_Click);
      FolderHistoryContextMenu.Items.Add(RemoveFolderMenuItem);
      RemoveAllFoldersMenuItem = new MenuItem();
      RemoveAllFoldersMenuItem.Header = "Remove all folders";
      RemoveAllFoldersMenuItem.Click += new RoutedEventHandler(RemoveAllFoldersMenuItem_Click);
      FolderHistoryContextMenu.Items.Add(RemoveAllFoldersMenuItem);
    
      // The context menu is assigned to each item in the list of the combo box and not to the combo box itself.
      if (FolderComboBox.ItemContainerStyle == null)
      {
        FolderComboBox.ItemContainerStyle = new Style(typeof(ComboBoxItem));
      }
      FolderComboBox.ItemContainerStyle.Setters.Add(new Setter(ContextMenuProperty, FolderHistoryContextMenu));
    }
    
    
    private void RemoveFolderMenuItem_Click(object sender, RoutedEventArgs e)
    {
      ComboBoxItem ClickedComboBoxItem = FolderHistoryContextMenu.PlacementTarget as ComboBoxItem;
      if (ClickedComboBoxItem != null)
      {
        object ComboBoxDataItem = ClickedComboBoxItem.DataContext;
        FolderComboBox.Items.Remove(ComboBoxDataItem);
      }
    }
    
    
    private void RemoveAllFoldersMenuItem_Click(object sender, RoutedEventArgs e)
    {
      FolderComboBox.Items.Clear();
    }
    
    20.05.2020
    Новые материалы

    Создание кнопочного меню с использованием HTML, CSS и JavaScript
    Вы будете создавать кнопочное меню, которое имеет состояние наведения, а также позволяет вам выбирать кнопку при нажатии на нее. Финальный проект можно увидеть в этом Codepen . Шаг 1..

    Внедрите OAuth в свои веб-приложения для повышения безопасности
    OAuth — это широко распространенный стандарт авторизации, который позволяет приложениям получать доступ к ресурсам от имени пользователя, не раскрывая его пароль. Это позволяет пользователям..

    Классы в JavaScript
    class является образцом java Script Object. Конструкция «class» позволяет определять классы на основе прототипов с чистым, красивым синтаксисом. // define class Human class Human {..

    Как свинг-трейдеры могут использовать ИИ для больших выигрышей
    По мере того как все больше и больше профессиональных трейдеров и активных розничных трейдеров узнают о возможностях, которые предоставляет искусственный интеллект и машинное обучение для улучшения..

    Как построить любой стол
    Я разработчик программного обеспечения. Я люблю делать вещи и всегда любил. Для меня программирование всегда было способом создавать вещи, используя только компьютер и мое воображение...

    Обзор: Машинное обучение: классификация
    Только что закончил третий курс курса 4 часть специализации по машинному обучению . Как и второй курс, он был посвящен низкоуровневой работе алгоритмов машинного обучения. Что касается..

    Разработка расширений Qlik Sense с qExt
    Использование современных инструментов веб-разработки для разработки крутых расширений Вы когда-нибудь хотели кнопку для установки переменной в приложении Qlik Sense? Когда-нибудь просили..