Какой обработчик события использовать для выбранного компонента ComboBox (выбранный элемент необязательно изменен)

objective: выдать событие, когда выбраны элементы в выпадающем списке combobox.

Проблема: если использовать «SelectionChanged», если пользователь выбирает тот же элемент, что и выбранный элемент, выбор не изменяется, и поэтому это событие не будет запущено.

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

(Разъяснение: проблема заключается в том, как вызывать «что-то», когда один и тот же элемент снова выбирается. В выпадающем списке нет дубликатов. Сценарий: первый раз выберите элемент 1, закройте раскрывающийся список. Затем снова откройте раскрывающийся список и выберите пункт 1, когда запускается некоторая функция.)

Решение : на данный момент, похоже, нет прямого решения для этого. Но в соответствии с каждым отдельным проектом могут быть способы обойти его. (Пожалуйста, обновите, если есть действительно хорошие способы сделать это). Благодарю.

У меня был тот же вопрос, и я наконец нашел ответ:

Вы должны обрабатывать BOTH событие SelectionChanged и DropDownClosed следующим образом:

В XAML:

  1 2 3  

В C #:

 private bool handle = true; private void ComboBox_DropDownClosed(object sender, EventArgs e) { if(handle)Handle(); handle = true; } private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { ComboBox cmb = sender as ComboBox; handle = !cmb.IsDropDownOpen; Handle(); } private void Handle() { switch (cmbSelect.SelectedItem.ToString().Split(new string[] { ": " }, StringSplitOptions.None).Last()) { case "1": //Handle for the first combobox break; case "2": //Handle for the second combobox break; case "3": //Handle for the third combobox break; } } 

Вы можете использовать событие «ComboBoxItem.PreviewMouseDown». Поэтому каждый раз, когда мышь на каком-то предмете, это событие будет запущено.

Чтобы добавить это событие в XAML, используйте «ComboBox.ItemContainerStyle», как в следующем примере:

       

и обрабатывать его как обычно

 void cmbItem_PreviewMouseDown(object sender, MouseButtonEventArgs e) { //...do your item selection code here... } 

Благодаря MSDN

Для меня ComboBox.DropDownClosed Event сделал это.

 private void cbValueType_DropDownClosed(object sender, EventArgs e) { if (cbValueType.SelectedIndex == someIntValue) //sel ind already updated { // change sel Index of other Combo for example cbDataType.SelectedIndex = someotherIntValue; } } 

Надеюсь, что вы найдете полезный трюк.

Вы можете связать оба события

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

И принудительно отодвинуть выбранный элемент на нуль внутри OnDropDownOpened

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

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

 private void OnSelectionChanged(object sender, SelectionChangedEventArgs e) { if (combobox.SelectedItem != null) { //Do something with the selected item } } 

Для приложений UWP (Windows Store) ни одно из вышеперечисленных действий не будет работать (PointerPressed не запускается, не существует событий Preview, DropDownClosed или SelectedIndexChanged)

Мне пришлось прибегнуть к прозрачной кнопке, накладывающейся на ComboBox (но не на стрелку вниз). Когда вы нажимаете на стрелку, список падает, как обычно, и срабатывает событие SelectionChanged Combo Box. Когда вы нажимаете в другом месте в Combo Box, срабатывает прозрачное нажатие кнопки кнопки, позволяющее повторно выбрать текущее значение Combo Box.

Некоторый рабочий код XAML:

       

Некоторый рабочий код C #:

  ///  /// It is impossible to simply click a ComboBox to select the shown value again. It always drops down the list of options but /// doesn't raise SelectionChanged event if the value selected from the list is the same as before /// /// To handle this, a transparent button is overlaid over the ComboBox (but not its dropdown arrow) to allow reselecting the old value /// Thus clicking over the dropdown arrow allows the user to select a new option from the list, but /// clicking anywhere else in the Combo re-selects the previous value ///  private void ClickedComboButValueHasntChanged(object sender, RoutedEventArgs e) { //You could also dummy up a SelectionChangedEvent event and raise it to invoke Function_SelectionChanged handler, below FunctionEntered(NewFunctionSelect.SelectedValue as string); } private void Function_SelectionChanged(object sender, SelectionChangedEventArgs e) { FunctionEntered(e.AddedItems[0] as string); } 

Вы можете попробовать « SelectedIndexChanged », это вызовет событие, даже если выбран тот же самый элемент.

Используйте событие SelectionChangeCommitted(object sender, EventArgs e) здесь

Эта проблема меня давно задевает, так как ни одна работа не работала для меня 🙁

Но хорошей новостью является то, что следующий метод отлично подходит для моего приложения.

Основная идея – зарегистрировать EventManager в App.xmal.cs чтобы App.xmal.cs PreviewMouseLeftButtonDownEvent для всех ComboBoxItem , а затем запустить SelectionChangedEvent если элемент выбора совпадает с выбранным элементом, т. App.xmal.cs Выбор выполняется без изменения индекса .

В 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())); } } } 

Затем, для всех комбинированных полей, зарегистрируйте SelectionChangedEvent обычным способом:

  

Теперь, если два индекса отличаются друг от друга, ничего особенного, кроме обычного процесса обработки событий; если два индекса одинаковы, сначала будет обрабатываться событие мыши на элементе, и таким образом запускается SelectionChangedEvent . Таким образом, обе ситуации вызовут SelectionChangedEvent 🙂

Это объект DependencyObject для присоединения к ComboBox.

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

 using System; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Web.UI.WebControls; namespace MyNamespace { public class ComboAlwaysFireSelection : DependencyObject { public static readonly DependencyProperty ActiveProperty = DependencyProperty.RegisterAttached( "Active", typeof(bool), typeof(ComboAlwaysFireSelection), new PropertyMetadata(false, ActivePropertyChanged)); private static void ActivePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var element = d as ComboBox; if (element == null) return; if ((e.NewValue as bool?).GetValueOrDefault(false)) { element.DropDownClosed += ElementOnDropDownClosed; element.DropDownOpened += ElementOnDropDownOpened; } else { element.DropDownClosed -= ElementOnDropDownClosed; element.DropDownOpened -= ElementOnDropDownOpened; } } private static void ElementOnDropDownOpened(object sender, EventArgs eventArgs) { _selectedIndex = ((ComboBox) sender).SelectedIndex; } private static int _selectedIndex; private static void ElementOnDropDownClosed(object sender, EventArgs eventArgs) { var comboBox = ((ComboBox) sender); if (comboBox.SelectedIndex == _selectedIndex) { comboBox.RaiseEvent(new SelectionChangedEventArgs(Selector.SelectionChangedEvent, new ListItemCollection(), new ListItemCollection())); } } [AttachedPropertyBrowsableForChildrenAttribute(IncludeDescendants = false)] [AttachedPropertyBrowsableForType(typeof(ComboBox))] public static bool GetActive(DependencyObject @object) { return (bool)@object.GetValue(ActiveProperty); } public static void SetActive(DependencyObject @object, bool value) { @object.SetValue(ActiveProperty, value); } } } 

и добавьте префикс пространства имен, чтобы сделать его доступным.

  

и тогда вам нужно прикрепить его так

  

Каждый экземпляр ComboBoxItem имеет событие PreviewMouseDown. Если вы подпишете свой собственный обработчик на этом событии на каждом ComboBoxItem, у вас будет возможность обрабатывать каждый клик по выпадающему списку.

 // Subscribe on ComboBoxItem-s events. comboBox.Items.Cast().ToList().ForEach(i => i.PreviewMouseDown += ComboBoxItem_PreviewMouseDown); private void ComboBoxItem_PreviewMouseDown(object sender, MouseButtonEventArgs e) { // your handler logic... }