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

时间:2013-01-14 20:57:19

标签: c# .net wpf combobox

我正在使用ComboBox将文本模板插入到RichEdit控件中(模板的名称位于ComboBox的选项列表中。)

除非用户再次在列表中选择相同的值,否则一切都很有效。然后SelectionChanged没有开火。根据事件的名称(选择已更改)有意义,但我需要知道该值已重新选择,因此我可以再次插入。

有没有办法知道从ComboBox中重新选择了一个项目?(或者更好的控件可以使用?)

我尝试使用DropDownClosed事件,但即使未重新选择该项,也会触发。 (他们打开下拉菜单然后点击另一个控件。)

5 个答案:

答案 0 :(得分:2)

听起来您使用组合框的方式与正常使用不一致。是否可以在插入所选模板的组合框旁边放置一个按钮。我认为这种行为对熟悉谷歌搜索搜索行为的用户来说效果更好

答案 1 :(得分:2)

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

您需要像这样处理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;
  }
}

答案 2 :(得分:1)

您需要提供一些代码来展示您尝试做的事情。如果某个项目已被选中,为什么RichEdit控件的模板尚未设置?
在处理WPF时,有助于熟悉视图模型的绑定,而不仅仅是ItemsSource,还有SelectedItem。根据您描述的场景,我将使用SelectedItem到视图模型的绑定,然后将RichEdit控件的模板绑定到相同的View Model属性,必要时使用值转换器。这样您就不需要处理点击事件等。如果视图模型的属性为DependencyProperty或触发PropertyChanged事件(请参阅INotifyPropertyChanged),则您的RichEdit控件的模板应自动反映下拉列表中的选择。

**编辑** 根据您的评论,我假设您想要的行为是基于组合选择设置文本,但允许用户自定义该文本。但是,如果已编辑,则应该能够重新选择组合值以重置文本。麻烦的是,如果项目已被选中,那么没有事件被触发进入。解决方案是,如果文本内容发生变化,这应该取消选择任何组合选择(因为组合不再反映文本框的内容。)绑定可以很好地管理这个:

为简单起见,此示例视图使用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>

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

接线:

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

这会绑定组合框,然后在选择项目时,文本框会自动更新。当文本框内容改变时,检查模板以查看它是否仍然匹配,如果不匹配,则取消选择组合项。如果条目与模板匹配,则自动选择该模板。

答案 3 :(得分:1)

我能找到的最好的方法是在下拉列表打开时清除所选值。这并不理想,因为用户无法将其先前的位置保留为参考点(适用于长列表)。但这是我能找到的最佳解决方案。

以下是我使用的代码:

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

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

答案 4 :(得分:1)

我会使用一个列表框。用户无需打开它。相反,他可以立即从列表中选择一个项目。此外,我不会将此功能附加到SelectionChanged事件,而是附加到MouseDoubleClick事件。这允许容易地选择和重新选择项目。我还会添加一个按钮,它会触发相同的功能。双击应该只是这个按钮的一种快捷方式,按钮也可以有一个描述性文字和/或一个图标,这使它更加直观。

即使用户使用箭头键上下移动,

SelectionChanged也会触发,但不应触发该功能。