用于ComboBox项目选择的事件处理程序(选定项目未必更改)

目标:选择combobox下拉列表中的项目时发出事件。

问题:但是,如果用户选择与当前正在选择的项目相同的项目,则使用“SelectionChanged”,则不会更改选择,因此不会触发此事件。

问题:只要鼠标单击该项目并且正在选择该项目,无论选择的项目是什么,我可以使用什么其他事件处理程序(或其他方式)来发布事件。

(澄清:问题是当再次选择相同的项目时如何触发“某事”。下拉列表中没有重复。场景:第一次选择项目1,关闭下拉列表。然后再次打开下拉框并选择触发某些function时的第1项。)

解决方案 :目前似乎没有直接的解决方案来做到这一点。 但根据每个项目,可以有办法解决它。 (如果确实有很好的方法,请更新)。 谢谢。

我有同样的问题,我终于找到了答案:

您需要像这样处理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事件做到了。

 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内强制选中的项为null

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

并使用OnSelectionChanged中的项目执行所需操作。 每次打开combobox时都会引发OnSelectionChanged,但您可以检查方法中的SelectedItem是否为null并跳过命令

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

对于UWP(Windowsapp store)应用程序,以上都不会起作用(PointerPressed不会触发;不存在Preview,DropDownClosed或SelectedIndexChanged事件)

我不得不求助于覆盖ComboBox的透明按钮(但不是它的下拉箭头)。 当您按下箭头时,列表会像往常一样下降,并且combobox的SelectionChanged事件会触发。 当您单击combobox上的任何其他位置时,透明按钮的单击事件将触发,允许您重新选择combobox的当前值。

一些有效的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)事件

这个问题困扰了我很长一段时间,因为没有一个解决办法为我工作:(

但好消息是,以下方法适用于我的应用程序。

基本思想是在App.xmal.cs注册EventManager以嗅探所有ComboBoxItem PreviewMouseLeftButtonDownEvent ,如果选择项与所选项相同则触发SelectionChangedEvent ,即在不改变索引的情况下执行选择

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

然后,对于所有combobox,以正常方式注册SelectionChangedEvent

  

现在,如果两个索引不同,那么普通的事件处理过程没有什么特别之处; 如果两个索引相同,则首先处理项目上的鼠标事件,从而触发SelectionChangedEvent 。 这样,两种情况都会触发SelectionChangedEvent 🙂

这是一个用于附加到ComboBox的DependencyObject。

它在打开下拉列表时记录当前选定的项目,如果在关闭下拉列表时仍然选择了相同的索引,则会触发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... }