5

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

这一切都很好,除非用户再次在列表中选择相同的值。然后SelectionChanged是不射击。根据事件的名称(Selection Changed ),这是有道理的,但我需要知道该值已被重新选择,以便我可以再次插入它。

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

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

4

5 回答 5

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;
  }
}
于 2014-09-18T14:07:38.197 回答
2

听起来您使用组合框的方式与正常使用不一致。在插入所选模板的组合框旁边有一个按钮是否有效。我认为对于熟悉 Google 搜索行为和搜索建议的用户来说,这种行为会更好

于 2013-01-15T00:41:13.800 回答
1

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

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

于 2013-01-15T00:54:27.443 回答
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>

视图模型:

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

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

于 2013-01-14T21:29:47.700 回答
1

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

这是我使用的代码:

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

private void OnDropDownOpened(object sender, EventArgs e)
{
   var comboBox = ((ComboBox)sender);
   comboBox.SelectedItem = null;
}
于 2013-01-14T21:54:30.300 回答