3

Google 検索結果の実装でカスタム ComboBox コントロールを作成していますが、矢印キーを使用すると問題が発生します。

問題の詳細
このビデオを見て、上矢印キーと下矢印キーの問題を説明し、出力パネルも見てください。

http://screencast.com/t/DFkmlDKR

ビデオでは、"a" を検索してみました (単なるテストです)。"a" で始まる Google 検索結果が返されたら、下矢印キーと上矢印キーを押しています。これらのキーを押すと、出力パネルに強調表示された項目が表示されます。
ここに画像の説明を入力

次に、次の文字「l」を入力しました。出力パネルで気付いた場合、選択は「null」になっていますが、まだ上と下の矢印キーを押しています。
ここに画像の説明を入力

マウス ポインターを使用してアイテムに再びカーソルを合わせると、再び機能し始めます。
ここに画像の説明を入力

私はこの問題に何日も悩まされており、解決策がわかりません。

このコントロールのテスト バージョンをアップロードしたので、あなたもそれで遊ぶことができます。ここにGoogleSuggestionComboBoxがあります
ここに画像の説明を入力

ここでの私の目標は、UP と DOWN の矢印キーを常に機能させることです。

コードのこのセクションでは、 ここに画像の説明を入力 追加しようとしました

SelectedIndex = 0;

ForEach ステートメントの後なので、コレクションが新しい結果で再設定されるたびに、最初の結果が選択されます。残念ながら、うまくいきませんでした。

問題を再生してテストできるように、テスト コードをダウンロードできます。http://sdrv.ms/1eWV3Bc ComboBox のコードもここにあります。

using GoogleSuggestionComboBox.Model;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace GoogleSuggestionComboBox
{
    public class ComboBoxExC : ComboBox
    {
        GoogleSuggest google;
        TextBox textbox;
        string _text = string.Empty;
        string _last_text = string.Empty;

        public ComboBoxExC()
        {
            if (DesignerProperties.GetIsInDesignMode(this))
            {

            }
            else
            {
                this.Loaded += ComboBoxExC_Loaded;

                google = new GoogleSuggest();
                google.OnGoogleSuggestAvailable += google_OnGoogleSuggestAvailable;

                // since we have OnSelectionChanged "disabled"
                // we need a way to know if the item in ComboBox is selected using mouse
                EventManager.RegisterClassHandler(typeof(ComboBoxItem), ComboBoxItem.MouseDownEvent, new MouseButtonEventHandler(OnItemMouseDown));
            }
        }

        void ComboBoxExC_Loaded(object sender, RoutedEventArgs e)
        {
            this.textbox = (TextBox)Template.FindName("PART_EditableTextBox", this);
        }

        private void OnItemMouseDown(object sender, MouseButtonEventArgs e)
        {
            var comboBoxItem = sender as ComboBoxItem;
            if (comboBoxItem != null && comboBoxItem.IsHighlighted)
            {
                Model_SuggestedQueries m = (Model_SuggestedQueries)comboBoxItem.Content;
                Go(m.Query);
            }
        }

        protected override void OnSelectionChanged(SelectionChangedEventArgs e)
        {
            // don't do anything so the .Text value won't change.

            //base.OnSelectionChanged(e);
        }

        protected override void OnPreviewKeyDown(KeyEventArgs e)
        {
            this.IsDropDownOpen = true;

            base.OnPreviewKeyDown(e);

            d("key: " + e.Key.ToString());

            if (this.SelectedItem != null)
            {
                Model_SuggestedQueries m = (Model_SuggestedQueries)this.SelectedItem;
                d("selected: " + m.Query);
            }
            else
            {
                d("null");
            }
        }

        protected override void OnPreviewKeyUp(KeyEventArgs e)
        {
            base.OnPreviewKeyUp(e);

            if (e.Key == Key.Enter)
            {
                if (this.SelectedItem == null)
                {
                    Go(this.Text);

                }
                else
                {
                    Model_SuggestedQueries m = (Model_SuggestedQueries)this.SelectedItem;
                    Go(m.Query);
                }
            }
            else
            {
                if (this.Text != this._last_text)
                {
                    google.LookForSuggestion(this.Text);

                    this._last_text = this.Text;
                }
            }
        }

        void google_OnGoogleSuggestAvailable(object sender, List<Model.Model_SuggestedQueries> suggestions)
        {
            this.Items.Clear();

            suggestions.ForEach((a) =>
            {
                this.Items.Add(a);
            });
        }

        void d(object a)
        {
            Debug.WriteLine(">>> " + a);
        }

        void Go(string query)
        {
            Process.Start("https://www.google.com.ph/search?q=" + query);

            // clear suggestions
            this.Items.Clear();
        }
    }
}

MainWindow.xaml

<Window x:Class="GoogleSuggestionComboBox.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:l="clr-namespace:GoogleSuggestionComboBox"
        Title="MainWindow" Height="133" Width="261" WindowStartupLocation="CenterScreen"
        >
    <Grid>
        <StackPanel Margin="10">
            <TextBlock Text="Search" />
            <l:ComboBoxExC 
                IsEditable="True" 
                IsTextSearchEnabled="False"
                TextSearch.TextPath="Query"
                >
                <l:ComboBoxExC.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Query}" />
                    </DataTemplate>
                </l:ComboBoxExC.ItemTemplate>
            </l:ComboBoxExC>
        </StackPanel>
    </Grid>
</Window>

ありがとう、
ジェイソン

4

2 に答える 2

-1

正確な問題はわかりませんが、ここに提案があります:

ComboBox をサブクラス化しないでください - その必要はありません。

1 つを MainForm にドロップして、コード ビハインドから操作するだけです。そのように操作する方がはるかに簡単です。通常ではないコンボボックスの動作方法を変更する必要がある場合にのみ、サブクラス化する必要があります。

テスト プロジェクトをダウンロードしようとしましたが、これは zip ファイルではなく、.7z ファイルであり、開くことができませんでした。

また、メインフォームはウィンドウです。それは問題ではないかもしれませんが、新しいプロジェクトを作成して、プロジェクトが提供するメイン フォームを操作してみてください。例外などをキャッチする MainForm を呼び出すアプリケーションで行われるいくつかの接続があり、問題が何であるかについてより多くのデータを提供する場合があります。

グレッグ

于 2013-10-01T21:00:26.363 に答える