我已经为我的组合框创建了一个代码,它可以借助存储过程(我正在使用Entity框架)在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。我不知道,怎么样 以任何其他方式使用combobox实现“在键入时搜索”,因为我的地址数据表非常大(百万条记录)。
提前感谢任何类型的帮助或代码示例。
弗拉基米尔
编辑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;
}
有没有办法在没有背景工作者的情况下加快速度?
答案 0 :(得分:0)
创建一个按钮,您将调用searchbutton 并在此按钮的click_event中调用运行backgroundworker的search()方法 填充组合框 清除你的组合框的key_press事件,它会工作 错误是你key_press事件调用你的搜索方法发生的每个键击 检索它
答案 1 :(得分:0)
您应该将项目放入列表中,使用该列表填充组合框。
然后将AutoCompleteMode
属性值设置为Suggest或Append或SuggestAppend,并将AutoCompleteSoucre
属性值设置为ListItems。
答案 2 :(得分:0)
对于“当您键入时搜索”,实际上“搜索时过滤”而不是搜索,您需要实现OnKeyDown或KeyPressed事件。
您要做的是获取搜索字符串,即事件发生时的当前文本,然后使用该字符串过滤主列表。通常会使用“Starts With”进行过滤,但您也可以使用“Contains”。然后你实时用过滤器的结果更新盒子的内容。这是通过更改和刷新数据源来实现的。
答案 3 :(得分:0)
这是我没有BackGroundWorker的最终解决方案。它可以快速使用我的大表,并在SQL Server上使用存储过程进行升级(如果使用实体框架)。我使用Timer来确保用户可以找到他正在搜索的值。
在这里,您可以看到我在此网站上找到的原始解决方案(感谢 Max Lambertini 和 algreat 的想法和工作理念):
C# winforms combobox dynamic autocomplete
我的解决方案:
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;
}
}