What event handler to use for ComboBox Item Selected (Selected Item not necessarily changed)

后端 未结 12 1532
囚心锁ツ
囚心锁ツ 2020-12-13 08:48

Goal: issue an event when items in a combobox drop down list is selected.

Problem: Using \"SelectionChanged\", however, if the user

相关标签:
12条回答
  • 2020-12-13 09:22

    You can try "SelectedIndexChanged", it will trigger the event even if the same item is selected.

    0 讨论(0)
  • 2020-12-13 09:22

    For UWP, I tried a different approach. I extended the ComboBox class, and processed the SelectionChanged and OnKeyUp events on the ComboBox as well as the Tapped event on the ComboBoxItems. In cases where I get a Tapped event or an Enter or Space key without first getting a SelectionChanged then I know the current item has been re-selected and I respond accordingly.

    class ExtendedComboBox : ComboBox
    {
        public ExtendedComboBox()
        {
            SelectionChanged += OnSelectionChanged;
        }
    
        protected override void PrepareContainerForItemOverride(Windows.UI.Xaml.DependencyObject element, object item)
        {
            ComboBoxItem cItem = element as ComboBoxItem;
            if (cItem != null)
            {
                cItem.Tapped += OnItemTapped;
            }
    
            base.PrepareContainerForItemOverride(element, item);
        }
    
        protected override void OnKeyUp(KeyRoutedEventArgs e)
        {
            // if the user hits the Enter or Space to select an item, then consider this a "reselect" operation
            if ((e.Key == Windows.System.VirtualKey.Space || e.Key == Windows.System.VirtualKey.Enter) && !isSelectionChanged)
            {
                // handle re-select logic here
            }
    
            isSelectionChanged = false;
    
            base.OnKeyUp(e);
        }
    
        // track whether or not the ComboBox has received a SelectionChanged notification
        // in cases where it has not yet we get a Tapped or KeyUp notification we will want to consider that a "re-select"
        bool isSelectionChanged = false;
        private void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            isSelectionChanged = true;
        }
    
        private void OnItemTapped(object sender, TappedRoutedEventArgs e)
        {
            if (!isSelectionChanged)
            {
                // indicates that an item was re-selected  - handle logic here
            }
    
            isSelectionChanged = false;
        }
    }
    
    0 讨论(0)
  • 2020-12-13 09:22

    Every ComboBoxItem instance has PreviewMouseDown event. If you will subscribe your custom handler on this event on every ComboBoxItem you will have opportunity to handle every click on the dropdown list.

    // Subscribe on ComboBoxItem-s events.
    comboBox.Items.Cast<ComboBoxItem>().ToList().ForEach(i => i.PreviewMouseDown += ComboBoxItem_PreviewMouseDown);
    
    private void ComboBoxItem_PreviewMouseDown(object sender, MouseButtonEventArgs e)
    {
         // your handler logic...         
    }
    
    0 讨论(0)
  • 2020-12-13 09:23

    I hope that you will find helpfull the following trick.

    You can bind both the events

    combobox.SelectionChanged += OnSelectionChanged;
    combobox.DropDownOpened += OnDropDownOpened;
    

    And force selected item to null inside the OnDropDownOpened

    private void OnDropDownOpened(object sender, EventArgs e)
    {
        combobox.SelectedItem = null;
    }
    

    And do what you need with the item inside the OnSelectionChanged. The OnSelectionChanged will be raised every time you will open the combobox, but you can check if SelectedItem is null inside the method and skip the command

    private void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (combobox.SelectedItem != null)
            {
               //Do something with the selected item
            }
        }
    
    0 讨论(0)
  • 2020-12-13 09:25

    This problem bugs me for a long time since none of the work-around worked for me :(

    But good news is, the following method works fine for my application.

    The basic idea is to register a EventManager in App.xmal.cs to sniff PreviewMouseLeftButtonDownEvent for all ComboBoxItem, then trigger the SelectionChangedEvent if the selecting item is the same as the selected item, i.e. the selection is performed without changing index.

    In App.xmal.cs:

    public partial class App : Application
    {
        protected override void OnStartup(StartupEventArgs e)
        {
            // raise selection change event even when there's no change in index
            EventManager.RegisterClassHandler(typeof(ComboBoxItem), UIElement.PreviewMouseLeftButtonDownEvent,
                                              new MouseButtonEventHandler(ComboBoxSelfSelection), true);
    
            base.OnStartup(e);
        }
    
        private static void ComboBoxSelfSelection(object sender, MouseButtonEventArgs e)
        {
            var item = sender as ComboBoxItem;
    
            if (item == null) return;
    
            // find the combobox where the item resides
            var comboBox = ItemsControl.ItemsControlFromItemContainer(item) as ComboBox;
    
            if (comboBox == null) return;
    
            // fire SelectionChangedEvent if two value are the same
            if ((string)comboBox.SelectedValue == (string)item.Content)
            {
                comboBox.IsDropDownOpen = false;
                comboBox.RaiseEvent(new SelectionChangedEventArgs(Selector.SelectionChangedEvent, new ListItem(), new ListItem()));
            }
        }
    }
    

    Then, for all combo boxes, register SelectionChangedEvent in a normal way:

    <ComboBox ItemsSource="{Binding BindList}"
              SelectionChanged="YourSelectionChangedEventHandler"/>
    

    Now, if two indices are different, nothing special but the ordinary event handling process; if two indices are the same, the Mouse Event on the item will first be handled, and thus trigger the SelectionChangedEvent. In this way, both situations will trigger SelectionChangedEvent :)

    0 讨论(0)
  • 2020-12-13 09:31

    It's easy, just add if (e.AddedItems.Count == 0) return; in the beggining of function like:

            private  void ComboBox_Symbols_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (e.AddedItems.Count == 0) 
            return;
            //Some Other Codes
        }
    
    0 讨论(0)
提交回复
热议问题