2

コンボボックスに自由に入力したい。入力を止めると、コンボボックス項目に入力依存の結果を入力する遅延タスクが発生します。問題は、私の入力がリストの最初の項目によって上書きされることです。入力を保持する方法はありますか?

私のサンプルコードは次のようになります:

public void PopulateCombo(JObject result)
    {
        Debug.WriteLine("Thread id: " + Thread.CurrentThread.ManagedThreadId);

        cbSearch.Items.Clear();
        if (result.Value<bool>("success") == true)
        {
            JArray arr = result.Value<JArray>("data");
            for (int i = 0; i < arr.Count; i++)
            {
                JToken item = arr[i];
                cbSearch.Items.Add(new ComboBoxItem( item.Value<string>("name"), item.Value<string>("_id")));
            }
            cbSearch.DroppedDown = true;
        }
    }

23.06に編集

私が実際にやろうとしていることの例を挙げています。

  1. コンボボックスが空です (項目がありません)
  2. ユーザーは、たとえば「ja」と入力し始めます。Combobox はクエリをバックエンドに送信します。呼び出しはユーザーの最後の入力から 1 秒の遅延で非同期であるため、問題になることはありません。
  3. 私のバックエンドはいくつかの結果を返します (Anton Jamison、James Aaron、James Hetfield など、50 に制限されています)
  4. ドロップダウンリストに結果を入力して開きたいのですが、コンボボックスのテキストとして「ja」を保持したいので、ユーザーは検索をさらに明確にすることができます。
  5. ユーザーは検索範囲を「ja h」に拡張します。バックエンドは James Hetfield で応答します。結果は 1 つの項目だけになり、コンボボックスのテキストを設定したり、上からの動作を維持したりできます。どちらが良いかはまだわかりません。

これはすべて実装されていますが、ステップ 4 で上記の関数を使用してコンボボックスに入力すると、コンボのテキストが「ja」からリストの最初の一致に変更されます。(例ではアントン・ジャミソン)。この動作を実装するための簡単なオプションがあったことはほぼ確実ですが、それが C# にあったかどうかはわかりません。

コメントについて :

  1. 良い試みでしたが失敗しました。コンボボックスの項目を入力すると、検索文字列がリストの最初の一致に変更されます。
  2. オートコンプリート機能を実装しようとはしていないと思います。
  3. DroppedDown についての良いキャッチ。編集版で動かします。
4

2 に答える 2

1

あなたが話した問題はありません。編集ボックス内のテキストは常に同じままです。私はVS2008を使用していますが、標準のComboBoxの名前をcbSearchに変更し、そのイベントをキャプチャしました(フォームのshowイベントと同様)。残りはうまく機能します。

いい仕事のように思えたので、私はそれをやった。ちらつきが見られますが、選択範囲も復元します。

最も難しかったのは同期でした。

それでも、私はあなたと何も違うことはしません..おそらく、空の ComobBox から再び開始するか、デフォルトのパラメーターのいくつかを変更した可能性があります。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void cbSearch_TextUpdate(object sender, EventArgs e)
        {
            lastUpdate = DateTime.Now;
            allowUpdate = true;
        }
        DateTime lastUpdate = DateTime.Now;

        volatile bool allowUpdate = false;
        private void BoxUpdate()
        {
            while (true)
            {
                Thread.Sleep(250);
                if (allowUpdate)
                {
                    var diff = DateTime.Now - lastUpdate;
                    if (diff.TotalMilliseconds > 1500)
                    {
                        allowUpdate = false;
                        this.InvokeEx(x =>
                        {
                            if (x.cbSearch.Text.Length > 0)
                            {
                                x.PopulateCombo(cbSearch.Text);
                            }
                        });
                    }
                }
            }
        }

        public void PopulateCombo(string text)
        {
            int sStart = cbSearch.SelectionStart;
            int sLen = cbSearch.SelectionLength;

            List<string> cbItems = new List<string>();
            for (int i = 0; i < 3; ++i)
                for (int j = 0; j < 3; ++j)
                    cbItems.Add(i + text + j);

            cbSearch.Items.Clear();

            {
                for (int i = 0; i < cbItems.Count; i++)
                {
                    cbSearch.Items.Add(cbItems[i]);
                }
                cbSearch.DroppedDown = true;
            }

            cbSearch.SelectionStart = sStart;
            cbSearch.SelectionLength = sLen;
        }

        private void Form1_Shown(object sender, EventArgs e)
        {
            ThreadPool.QueueUserWorkItem(x =>
            {
                BoxUpdate();
            });
        }
    }

    public static class ISynchronizeInvokeExtensions
    {
        public static void InvokeEx<T>(this T @this, Action<T> action)
            where T : System.ComponentModel.ISynchronizeInvoke
        {
            if (@this.InvokeRequired)
            {
                @this.Invoke(action, new object[] { @this });
            }
            else
            {
                action(@this);
            }
        }
    }
}
于 2012-06-27T16:51:50.580 に答える
0

コメント1 +いくつかの微調整のヒントで同じタスクを実行できました。これが仕事をする私の最終的なコードです:

    private void cbSearch_TextUpdate(object sender, EventArgs e)
    {
        timer1.Stop();
        timer1.Dispose();
        timer1 = null;

        timer1 = new System.Windows.Forms.Timer();
        timer1.Tick += new EventHandler(timer1_Tick);
        timer1.Interval = 1000;
        timer1.Start();
    }

    delegate void MethodDelegate(JObject result);

    void timer1_Tick(object sender, EventArgs e)
    {
        timer1.Stop();
        Debug.WriteLine(this.cbSearch.Text);

        Debug.WriteLine("Thread id: " + Thread.CurrentThread.ManagedThreadId);
        Dictionary<string, object> parameters = new Dictionary<string, object>();
        parameters["query"] = this.cbSearch.Text ?? "";
        this.session.rpc["advanced_search"].execAsync(parameters, results =>
        {
            this.BeginInvoke(new MethodDelegate(PopulateCombo), new object[] {results.GetResult()});
        });
    }

    public void PopulateCombo(JObject result)
    {
        Debug.WriteLine("Thread id: " + Thread.CurrentThread.ManagedThreadId);

        this.selectedPatientId = "";
        string text = cbSearch.Text;
        cbSearch.DroppedDown = false;

        cbSearch.Items.Clear();
        if (result.Value<bool>("success") == true)
        {
            JArray arr = result.Value<JArray>("data");
            for (int i = 0; i < arr.Count; i++)
            {
                JToken item = arr[i];
                cbSearch.Items.Add(new ComboBoxItem( item.Value<string>("name"), item.Value<string>("_id")));
            }

            try
            {
                this.cbSearch.TextUpdate -= new System.EventHandler(this.cbSearch_TextUpdate);
                cbSearch.DroppedDown = true; 
                cbSearch.Text = text;
                cbSearch.Select(cbSearch.Text.Length, 0);

            }
            finally {
                this.cbSearch.TextUpdate += new System.EventHandler(this.cbSearch_TextUpdate);
            }
        }
    }
于 2012-07-05T11:44:24.057 に答える