2

ストアド プロシージャを使用して、Sql Server 上の非常に大きなテーブルでアドレスを検索できるコンボボックスのコードを作成しました (エンティティ フレームワークを使用しています)。ストアド プロシージャは 10 件のヒットを返し、コードはコンボボックスに検索結果を入力します。これを行うために、私は BackgroundWorker を使用しています。

しかし、ここで大きな問題が発生しました: - コンボボックスには検索結果が表示されますが、常に最初の項目が選択されています。文字だけを入力しても、テキスト全体が選択されます。

  • その後、住所の検索は機能しなくなりました。これらの 10 件の結果のみを検索しますが、これを解決する方法がわかりません。ここに問題を引き起こす私のコード全体があります:

    public String searchedItem = "";    
    public delegate void DelegateUpdateComboboxSelection(ComboBox myCombo,string value,int count);
    
    BackgroundWorker m_bgworker = new BackgroundWorker();        
    static AutoResetEvent resetWorker = new AutoResetEvent(false);
    
    m_bgworker.WorkerSupportsCancellation = true;
    m_bgworker.DoWork += new DoWorkEventHandler(FillComboboxBindingList);
    m_bgworker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(m_bgworker_RunWorkerCompleted);
    
    BindingList<spIskalnikNaslovi_Result1> m_addresses = new BindingList<SP_Result1>(); 
    
    
    void m_bgworker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        int count = (int)((object[])e.Result)[0];
        string value = (string)((object[])e.Result)[1];
        ComboBox myCombo = (ComboBox)((object[])e.Result)[2];
        DelegateUpdateComboboxSelection ndelegate = new DelegateUpdateComboboxSelection(UpdateComboSelection);
        if (this.InvokeRequired)
        {
            Invoke(ndelegate, new object[] {myCombo, value, count});
            return; 
        }
        else
        {
            UpdateComboSelection(myCombo, value, count);
            return; 
        }               
    }
    
    private void UpdateComboSelection(ComboBox myCombo, String value, int count)
    {
        myCombo = comboBox9;
        myCombo.DataSource = m_addresses;
        searchedItem = myCombo.Text;  
        if (count > 0)
        {
            myCombo.SelectionStart = value.Length;
            myCombo.SelectionLength = searchedItem.Length - value.Length;
            myCombo.DroppedDown = true;
        }
        else
        {
            myCombo.DroppedDown = false;
            myCombo.SelectionStart = value.Length;
        }
    } 
    
    public void FillComboboxBindingList(object sender, DoWorkEventArgs e)
    {
        if (m_bgworker.CancellationPending)
        {
            resetWorker.Set();
            e.Cancel = true;
            return;
        }
        else
        {
            string value = (String)((Object[])e.Argument)[0];
            List<SP_Result1> result;
            result = _vsebina.SP_searcher(value).ToList<SP_Result1>();
            m_addresses = new BindingList<SP_Result1>();
    
            foreach (SP_Result1 rez in result)
            {
                if (m_addresses.Contains(rez))
                {
                    continue;
                }
                else
                {
                    m_addresses.Add(rez);
                }
            }
            foreach (SP_Result1 r in m_addresses.ToArray())
            {
                if (!result.Contains(r))
                {
                    m_addresses.Remove(r);
                }
            }
            e.Result = new object[] { rezultat.Count, vrednost, null };
            return;
        }
    }
    
    private void comboBox9_KeyUp(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == Keys.Back)
        {
            int searchStart = comboBox9.SelectionStart;
            if (searchStart > 0)
            {
                searchStart--;
                if (searchStart == 0)
                {
                    comboBox9.Text = "";
                }
                else
                {
                    comboBox9.Text = comboBox9.Text.Substring(0, searchStart + 1);
                }
            }
            else 
            {
                searchStart = 0;
            }
            e.Handled = true;
        }
    }
    
    private void comboBox9_Enter(object sender, EventArgs e)
    {
        comboBox9.SelectionStart = 0;
        comboBox9.SelectionLength = 0;
    }
    
    private void comboBox9_Click(object sender, EventArgs e)
    {
        comboBox9.Text = "";
    }
    
    private void comboBox9_KeyPress(object sender, KeyPressEventArgs e)
    {
        Search();
    }
    
    public void Search()
    {
        if (comboBox9.Text.Length < 4)
        {
            return;
        }
        else
        {
            if (m_bgworker.IsBusy)
            {
               m_bgworker.CancelAsync();
    
               m_bgworker = new BackgroundWorker();
               m_bgworker.WorkerSupportsCancellation = true;
               m_bgworker.DoWork += new DoWorkEventHandler(FillComboboxBindingList);
               m_bgworker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(m_bgworker_RunWorkerCompleted);
            }
            m_bgworker.RunWorkerAsync(new object[] { comboBox9.Text, comboBox9 });
        }  
    }
    

多分誰かが私を啓発することができます、私が間違っていること。BackgroundWorker を使用するのはこれが初めてです。アドレスを含む私のデータテーブルは非常に大きい(100万レコード)ため、他の方法でコンボボックスを使用して「入力時に検索」を実現する方法がわかりません。

あらゆる種類のヘルプまたはコード例を事前に感謝します。

ウラジミール

編集 1: BackGroundWorker を使用する前のコードです。機能しましたが、検索が非常に遅くなります (最大 10 秒かかる場合があります)。

    private void comboBox9_TextChanged(object sender, EventArgs e)
    {
        if (comboBox9.Text.Length < 4)
        {
            return;
        }
        else
        {
            FillCombobox(comboBox9.Text, comboBox9);
        }

    }

    public void FillCombobox(string value, ComboBox myCombo)
    {
        List<spIskalnikNaslovi_Result1> result;
        result = _vsebina.spIskalnikNaslovi1(value).ToList(); 
        if (result.Count() > 0)
        {
            myCombo.DataSource = result;
            myCombo.ValueMember = "HS_MID";
            myCombo.DisplayMember = "NASLOV1";
            var searchedItem = myCombo.Items[0].ToString();
            myCombo.SelectionStart = value.Length;
            myCombo.SelectionLength = searchedItem.Length - value.Length;
            myCombo.DroppedDown = true;
        }
        else
        {
            myCombo.DroppedDown = false;
            myCombo.SelectionStart = value.Length;
        }
        return;
    }

バックグラウンドワーカーなしでこれをスピードアップする方法はありますか?

4

4 に答える 4

0

BackGroundWorker を使用しない最終的な解決策を次に示します。私の大きなテーブルですばやく動作し、SQL Server でストアド プロシージャを使用できるようにアップグレードされています (Entity Framework を使用している場合)。Timer を使用して、ユーザーが検索している値を確実に見つけられるようにします。

ここで、私がこのサイトで見つけた元のソリューションを見ることができます ( Max Lambertiniに感謝 し、アイデアと作業コンセプトについてalgreatに感謝します)。

C#winformコンボボックスの動的オートコンプリート

私の解決策:

    private bool _canUpdate = true;
    private bool _needUpdate = false;
    List<spIskalnikNaslovi_Result1> dataFound;

    private void comboBox12_TextChanged(object sender, EventArgs e)
    {
        if (_needUpdate)
        {
            if (_canUpdate)
            {
                _canUpdate = false;
                refreshData();
            }
            else
            {
                restartTimer();
            }
        }
    }

    private void comboBox12_KeyUp(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == Keys.Back)
        {
            int searchStart = comboBox12.SelectionStart;
            if (searchStart > 0)
            {
                searchStart--;
                if (searchStart == 0)
                {
                    comboBox12.Text = "";
                }
                else
                {
                    comboBox12.Text = comboBox12.Text.Substring(0, searchStart + 1);
                }
            }
            else 
            {
                searchStart = 0;
            }
            e.Handled = true;
        }
    }

    private void comboBox12_TextUpdate(object sender, EventArgs e)
    {
        _needUpdate = true;
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        _canUpdate = true;
        timer1.Stop();
        refreshData();
    }

    private void refreshData()
    {
        if (comboBox12.Text.Length > 1)
        {
            FillCombobox(comboBox12.Text, comboBox12);
        }
    }

    private void restartTimer()
    {
        timer1.Stop();
        _canUpdate = false;
        timer1.Start();
    }


    private void FillCombobox(string value, ComboBox myCombo)
    {
        dataFound = _vsebina.spIskalnikNaslovi1(value).ToList();
        if (dataFound.Count() > 0)
        {
            myCombo.DataSource = dataFound;
            myCombo.ValueMember = "HS_MID";
            myCombo.DisplayMember = "NASLOV1";
            var searchedItem = myCombo.Items[0].ToString();
            myCombo.SelectionStart = value.Length;
            myCombo.SelectionLength = searchedItem.Length - value.Length;
            myCombo.DroppedDown = true;
            return;
        }
        else
        {
            myCombo.DroppedDown = false;
            myCombo.SelectionStart = value.Length;
            return;
        }            
    }
于 2012-08-21T10:17:58.860 に答える
0

「入力時に検索」、つまり実際には検索よりも「入力時にフィルター」を行うには、OnKeyDown または KeyPressed イベントを実装する必要があります。

イベント発生時の現在のテキストである検索文字列を取得し、その文字列を使用してマスター リストをフィルター処理します。通常、フィルタリングには "Starts With" を使用しますが、単純に "Contains" を使用することもできます。次に、フィルターからの結果でボックスの内容をライブ更新します。これは、データソースを変更および更新することによって実現されます。

于 2012-08-17T19:53:22.060 に答える
0

searchbutton を呼び出すボタンを作成し、このボタンの click_event で、コンボボックスを満たすバックグラウンド ワーカーを実行する search() メソッドを呼び出します。あなたの検索方法はそれを取得します

于 2012-08-17T18:18:05.267 に答える
0

リストでアイテムを取得し、そのリストを使用してコンボボックスにデータを入力する必要があります。

次に、AutoCompleteModeプロパティ値を Suggest または Append または SuggestAppend に設定し、AutoCompleteSoucreプロパティ値を ListItems に設定します。

于 2012-08-17T19:26:36.553 に答える