简体   繁体   English

如何知道ComboBox中何时“重新选择”某个值?

[英]How can I know when a value is “re-selected” in a ComboBox?

I am using a ComboBox to insert a text template into a RichEdit control (the name of the template is in the picklist for the ComboBox.) 我正在使用ComboBox将文本模板插入到RichEdit控件中(模板的名称位于ComboBox的选项列表中。)

It all works great except when the user selects the same value in the list again. 除非用户再次在列表中选择相同的值,否则一切都很有效。 Then the SelectionChanged is not firing. 然后SelectionChanged没有触发。 That makes sense based on the name of the event (Selection Changed ), but I need to know that the value was re-selected so I can insert it again. 这基于事件的名称(选择更改 )是有意义的,但我需要知道该值已重新选择,因此我可以再次插入它。

Is there a way to know that an item was re-selected from the ComboBox? 有没有办法知道从ComboBox中重新选择了一个项目? (Or a better control to use?) (或者更好的控制使用?)

I tried using the DropDownClosed event, but that fires even if the item was not re-selected. 我尝试使用DropDownClosed事件,但即使没有重新选择该项,也会触发。 (They open the drop down then click on another control.) (他们打开下拉菜单然后点击另一个控件。)

It sounds like the way you are using your combo box isn't consistent with normal usage. 听起来你使用组合框的方式与正常使用不一致。 Would it work to have a button next to the combo box that inserted the selected template. 是否可以在插入所选模板的组合框旁边放置一个按钮。 I think that behavior would work better for users who are familiar with the behavior of Google search with search sugestions 我认为这种行为对熟悉谷歌搜索搜索行为的用户更有效

I had the same question and I finally found the answer: 我有同样的问题,我终于找到了答案:

You need to handle BOTH the SelectionChanged event and the DropDownClosed like this: 您需要像这样处理SelectionChanged事件和DropDownClosed:

In XAML: 在XAML中:

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

In C#: 在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;
  }
}

You'll need to provide some code to show what you're trying to do. 您需要提供一些代码来显示您要执行的操作。 If an item is already selected, why would the RichEdit control's template not already be set anyway? 如果已经选择了某个项目,为什么还没有设置RichEdit控件的模板呢?
When dealing with WPF it helps to get familiar with binding to view models, not just for things like ItemsSource but also SelectedItem . 在处理WPF时,它有助于熟悉绑定到视图模型,而不仅仅是像ItemsSource这样的东西,还有SelectedItem Given the scenario you describe I would use a binding for the SelectedItem to the View Model then bind the RichEdit control's template to the same View Model property, using a value converter if necessary. 根据您描述的场景,我将使用SelectedItem绑定到View Model,然后将RichEdit控件的模板绑定到相同的View Model属性,必要时使用值转换器。 This way you don't need to mess around with click events and the like. 这样您就不需要处理点击事件等。 Provided the View Model's property is a DependencyProperty or fires a PropertyChanged event (see INotifyPropertyChanged ) your RichEdit control's template should automatically reflect the selection in the drop-down. 如果View Model的属性是DependencyProperty或触发PropertyChanged事件(请参阅INotifyPropertyChanged ),则RichEdit控件的模板应自动反映下拉列表中的选择。

** Edit ** Based on your comments I'm assuming the behaviour you want is to set text based on a combo selection but allow the user to customise that text. **编辑**根据您的评论,我假设您想要的行为是根据组合选择设置文本,但允许用户自定义该文本。 However, if edited they should be able to re-select the combo value to reset the text. 但是,如果已编辑,则应该能够重新选择组合值以重置文本。 The trouble is that if the item is already selected then there is no event fired to hook into. 麻烦的是,如果项目已被选中,那么没有事件被触发进入。 The solution is that if the text contents change, this should de-select any combo selection (since the combo no longer reflects the contents of the text box.) Bindings can manage this quite nicely: 解决方案是,如果文本内容发生更改,则应取消选择任何组合选择(因为组合不再反映文本框的内容。)绑定可以非常好地管理:

This example view uses a TextBox for simplicity: 此示例视图使用TextBox以简化:

<Window x:Class="UISample.UITemplateSample"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="UITemplateSample" Height="300" Width="300">
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="auto"/>
        <RowDefinition/>
    </Grid.RowDefinitions>

    <ComboBox ItemsSource="{Binding Path=Templates}" SelectedItem="{Binding Path=SelectedTemplate}" DisplayMemberPath="Name"/>
    <TextBox Grid.Row="1" AcceptsReturn="True" TextWrapping="Wrap" Text="{Binding Path=Text}"/>
</Grid>

The ViewModel: ViewModel:

    class TemplateSampleViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public ObservableCollection<TextTemplate> Templates
    {
        get;
        private set;
    }

    private TextTemplate _selectedTemplate;
    public TextTemplate SelectedTemplate
    {
        get{ return _selectedTemplate; }
        set
        {
            if ( _selectedTemplate == value )
                return;
            _selectedTemplate = value;
            if (_selectedTemplate != null)
                Text = _selectedTemplate.TemplateText;
            firePropertyChanged("SelectedTemplate");
        }
    }

    private string _text;
    public string Text
    {
        get { return _text; }
        set
        {
            if ( _text == value )
                return;

            _text = value;
            firePropertyChanged( "Text" );
            var matchingTemplate = Templates.FirstOrDefault( t => t.TemplateText == _text );
            SelectedTemplate = matchingTemplate;

        }
    }

    public TemplateSampleViewModel(IEnumerable<TextTemplate> templates)
    {
        Templates = new ObservableCollection<TextTemplate>(templates);
    }

    private void firePropertyChanged(string propertyName)
    {
        if ( PropertyChanged != null )
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

And wiring it up: 接线:

            var viewModel = new TemplateSampleViewModel(new[]
                                                        {
                                                            new TextTemplate {Name = "First", TemplateText = "This is the first item"},
                                                            new TextTemplate {Name = "Second", TemplateText = "This is the second item"},
                                                            new TextTemplate {Name = "Third", TemplateText = "This is the third item"},
                                                        });
        var test = new UITemplateSample {DataContext = viewModel};
        test.Show();

This binds the combo box, then as items are selected, the text box is updated automatically. 这会绑定组合框,然后在选择项目时,文本框会自动更新。 When the text box contents change, the template is inspected to see if it still matches and if not, the combo item is de-selected. 当文本框内容改变时,检查模板以查看它是否仍然匹配,如果不匹配,则取消选择组合项。 If the entry matches a template then that template is selected automatically. 如果条目与模板匹配,则自动选择该模板。

The best I could find was to clear out the selected value as the dropdown opens. 我能找到的最好的方法是在下拉列表打开时清除所选值。 This is not ideal as the user does not get to keep their previous location as a point of reference (good for long lists). 这并不理想,因为用户无法将其先前的位置保留为参考点(适用于长列表)。 But it is the best solution I can find. 但这是我能找到的最佳解决方案。

Here is the code I used: 这是我使用的代码:

ctor()
{
     myComboBox.DropDownOpened += OnDropDownOpened;
}

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

I would use a list box. 我会用一个列表框。 The user does not need to open it. 用户无需打开它。 Instead he can immediately select an item from the list. 相反,他可以立即从列表中选择一个项目。 Also I would not attach this function to the SelectionChanged event but to the MouseDoubleClick event. 此外,我不会将此函数附加到SelectionChanged事件,而是附加到MouseDoubleClick事件。 This allows selecting and reselecting an item easily. 这允许容易地选择和重新选择项目。 Also I would add a button, which triggers the same function. 我还会添加一个按钮,它会触发相同的功能。 The double click should only be a kind of shortcut for this button, also the button can have a descriptive text and/or an icon, which makes it even more intuitive. 双击应仅是此按钮的一种快捷方式,按钮也可以具有描述性文本和/或图标,这使其更加直观。

SelectionChanged will fire even when the user moves up and down using the arrow keys, but the function should not be triggered then. 即使用户使用箭头键上下移动, SelectionChanged也会触发,但不应触发该功能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何根据组合框的选定值,我可以在 numericupdown 中允许值 &gt;= 0? - How depending the selected value of a combobox, i can allow in a numericupdown the value to be >= 0? 选择 ComboBox 中的特定值时,如何使图像出现在 Windows Forms C# 中? - How can I make an image appear in Windows Forms C# when a specific value in ComboBox is selected? 如何在 WPF MVVM 中的 combobox 中输入默认选择值 - How can I put default selected value in combobox in WPF MVVM 如何分配组合框中所选项目的值? - How can I assign the value of a selected item in a combobox? 我如何选择组合框的值? - How i do combobox selected value can work? 如何修改 Combobox 的选定文本? - How I can modify the Selected text of Combobox? C# CaliburnMicro:如何根据在数据网格中选择的项目自动在组合框中显示值? - C# CaliburnMicro: How can I automatically display a value in a combobox depending on which item is selected in a datagrid? 发布后如何在ASP.net的组合框中请求选定的值? - How can I request a selected value in a combobox in ASP.net after a post? 当我选择 combobox1 最后一个值时,combobox2 最后一个值将被自动选择 - When i select the combobox1 last value the combobox2 last value will be automatically selected 如何处理有选择的值可以为null的有界组合框? - How to handle a bounded combobox where selected value can be null?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM