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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用于ComboBox项目选择的事件处理程序(选定项目未必更改)相关的知识,希望对你有一定的参考价值。

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

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

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

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

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

答案

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

您需要像这样处理SelectionChanged事件和DropDownClosed:

在XAML中:

<ComboBox Name="cmbSelect" SelectionChanged="ComboBox_SelectionChanged" DropDownClosed="ComboBox_DropDownClosed">
    <ComboBoxItem>1</ComboBoxItem>
    <ComboBoxItem>2</ComboBoxItem>
    <ComboBoxItem>3</ComboBoxItem>
</ComboBox>

在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事件。如果您将在每个ComboBoxItem上订阅此事件的自定义处理程序,您将有机会处理下拉列表中的每次单击。

// 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...         
}
另一答案

对于UWP,我尝试了不同的方法。我扩展了ComboBox类,并处理了ComboBox上的SelectionChanged和OnKeyUp事件以及ComboBoxItems上的Tapped事件。如果我在没有获得SelectionChanged的情况下获得Tapped事件或Enter或Space键,那么我知道当前项目已被重新选择并且我做出相应的响应。

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;
    }
}
另一答案

您可以使用“ComboBoxItem.PreviewMouseDown”事件。因此,每当鼠标停在某个项目上时,此事件将被触发。

要在XAML中添加此事件,请使用“ComboBox.ItemContainerStyle”,如下例所示:

   <ComboBox x:Name="MyBox"
        ItemsSource="{Binding MyList}"
        SelectedValue="{Binding MyItem, Mode=OneWayToSource}" >
        <ComboBox.ItemContainerStyle>
            <Style>
                <EventSetter Event="ComboBoxItem.PreviewMouseDown"
                    Handler="cmbItem_PreviewMouseDown"/>
            </Style>
        </ComboBox.ItemContainerStyle>
   </ComboBox>

像往常一样处理它

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中的项目执行所需操作。每次打开组合框时都会引发OnSelectionChanged,但您可以检查方法中的SelectedItem是否为null并跳过命令

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

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

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

一些有效的XAML代码:

                <Grid x:Name="ComboOverlay" Margin="0,0,5,0"> <!--See comments in code behind at ClickedComboButValueHasntChanged event handler-->
                    <ComboBox x:Name="NewFunctionSelect" Width="97" ItemsSource="{x:Bind Functions}"
                          SelectedItem="{x:Bind ChosenFunction}" SelectionChanged="Function_SelectionChanged"/>
                    <Button x:Name="OldFunctionClick" Height="30" Width="73" Background="Transparent" Click="ClickedComboButValueHasntChanged"/>
                </Grid>

一些有效的C#代码:

    /// <summary>
    /// 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
    /// </summary>
    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”,即使选择了相同的项目,它也会触发事件。

另一答案

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

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

基本思想是在EventManager中注册App.xmal.cs以嗅探所有PreviewMouseLeftButtonDownEventComboBoxItem,然后如果所选项目与所选项目相同则触发Selection

以上是关于用于ComboBox项目选择的事件处理程序(选定项目未必更改)的主要内容,如果未能解决你的问题,请参考以下文章

Windows 10 中的 XAML ComboBox 选定项背景颜色

如何从选定的 WPF ComboBox 项 C# 中显示内容

WPF MVVM 将 ComboBox 绑定到 Datagrid 选定项

如何获取 Datagridview Combobox 选定项的 TEXT?

ComboBox SelectedIndexChanged 事件:如何获取之前选择的索引?

更改 ComboBox 文本但未选择项