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。我不知道如何以任何其他方式使用组合框实现“键入时搜索”,因为我的地址数据表非常大(百万条记录)。

在此先感谢您提供任何帮助或代码示例。

弗拉基米尔

编辑 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

制作一个按钮,您将调用 searchbutton 并在此按钮的 click_event 中调用您的 search() 方法,该方法运行填充组合框的 backgroundworker 清除您的组合框的 key_press 事件,它会起作用的错误是您调用每个按键的 key_press 事件发生你的搜索方法所以检索它

于 2012-08-17T18:18:05.267 回答
0

您应该将您的项目放在一个列表中,使用该列表来填充您的组合框。

然后将AutoCompleteMode属性值设置为 Suggest 或 Append 或 SuggestAppend,并将AutoCompleteSoucre属性值设置为 ListItems。

于 2012-08-17T19:26:36.553 回答
0

对于“Search as you Type”,实际上是“Filter as you Type”而不是搜索,您需要实现 OnKeyDown 或 KeyPressed 事件。

您要做的是获取搜索字符串,即事件发生时的当前文本,然后使用该字符串过滤主列表。通常人们会使用“开始于”进行过滤,但您也可以简单地使用“包含”。然后,您使用过滤器的结果实时更新框的内容。这是通过更改和刷新数据源来完成的。

于 2012-08-17T19:53:22.060 回答
0

这是我没有 BackGroundWorker 的最终解决方案。它适用于我的大表,并已升级为使用 SQL Server 上的存储过程(如果您使用实体框架)。我使用 Timer 来确保用户可以找到他正在搜索的值。

在这里你可以看到我在这个网站上找到的原始解决方案(感谢Max Lambertinialgreat 的想法和工作概念):

C# winforms 组合框动态自动完成

我的解决方案:

    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 回答