我如何知道一个值何时被“重新选择”?在组合框中

本文关键字:重新选择 选择 组合 新选择 何知道 一个 何时 | 更新日期: 2023-09-27 17:52:55

我正在使用ComboBox将文本模板插入到richit控件中(模板的名称在ComboBox的选择列表中)

除了当用户再次在列表中选择相同的值时,这一切都很好。那么SelectionChanged没有发射。根据事件的名称(SelectionChanged),这是有意义的,但我需要知道该值已被重新选择,以便我可以再次插入它。

是否有一种方法可以知道从组合框中重新选择了一个项目?(或者使用更好的控件?)

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

我如何知道一个值何时被“重新选择”?在组合框中

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

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

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

我能找到的最好的方法是在下拉菜单打开时清除选中的值。这并不理想,因为用户不能保留他们以前的位置作为参考点(对于长列表来说很好)。但这是我能找到的最好的解决办法。

下面是我使用的代码:
ctor()
{
     myComboBox.DropDownOpened += OnDropDownOpened;
}
private void OnDropDownOpened(object sender, EventArgs e)
{
   var comboBox = ((ComboBox)sender);
   comboBox.SelectedItem = null;
}

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

SelectionChanged即使在用户使用方向键上下移动时也会触发,但此时不应触发该功能。

您需要提供一些代码来显示您要做的事情。如果一个项目已经被选中,为什么RichEdit控件的模板还没有被设置好呢?
在处理WPF时,熟悉绑定到视图模型是有帮助的,不仅仅是ItemsSource,还有SelectedItem。鉴于您描述的场景,我将使用SelectedItem到视图模型的绑定,然后将RichEdit控件的模板绑定到相同的视图模型属性,必要时使用值转换器。这样你就不需要搞砸点击事件之类的东西了。如果视图模型的属性是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();

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