5

ComboBox を使用してテキスト テンプレートを RichEdit コントロールに挿入しています (テンプレートの名前は ComboBox の選択リストにあります)。

ユーザーがリストで同じ値を再度選択した場合を除いて、すべてうまく機能します。その後、SelectionChanged発砲していません。これは、イベントの名前 (Selection Changed )に基づくと理にかなっていますが、再度挿入できるように、値が再選択されたことを知る必要があります。

ComboBox から項目が再選択されたことを知る方法はありますか? (または、使用するより良いコントロール?)

イベントを使用してみDropDownClosedましたが、アイテムを再選択しなくても発生します。(ドロップダウンを開き、別のコントロールをクリックします。)

4

5 に答える 5

2

コンボ ボックスの使用方法が、通常の使用方法と一致していないようです。選択したテンプレートを挿入したコンボ ボックスの横にボタンを配置するとうまくいきますか。検索候補を使った Google 検索の動作に慣れているユーザーの方が動作がうまくいくと思います

于 2013-01-15T00:41:13.800 に答える
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 に答える
1

何をしようとしているのかを示すために、いくつかのコードを提供する必要があります。アイテムが既に選択されている場合、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>

ビューモデル:

    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 に答える
1

リストボックスを使用します。ユーザーが開く必要はありません。代わりに、リストからアイテムをすぐに選択できます。SelectionChangedまた、この関数をイベントではなくイベントにアタッチしますMouseDoubleClick。これにより、項目の選択と再選択が簡単になります。また、同じ機能をトリガーするボタンを追加します。ダブルクリックは、このボタンの一種のショートカットにすぎません。また、ボタンには説明テキストやアイコンを含めることができるため、さらに直感的になります。

SelectionChangedユーザーが矢印キーを使用して上下に移動しても起動しますが、その場合は関数をトリガーしないでください。

于 2013-01-15T00:54:27.443 に答える