根据用户类型从API设置动态数据源
本文关键字:设置 动态 数据源 API 用户 类型 | 更新日期: 2023-09-27 18:02:28
我的要求是
1)。用户应该能够键入输入2).需要通过查询web api获取给定输入的每个按键的匹配结果。3).结果应以下拉式显示。用户应该能够从项目列表中选择任何项目。4).需要用选中的项目文本查询API获取详细信息
为了实现上述目标,我采用了一个组合框来处理keyup和keydown事件。
这是我的代码。
private void cmbSearch_KeyDown(object sender, KeyEventArgs e)
{
try
{
if (e.KeyCode == Keys.Up || e.KeyCode == Keys.Down)
{
isKeyDownOrKeyUp = true;
}
else
{
isKeyDownOrKeyUp = false;
}
if (e.KeyCode == Keys.Up || e.KeyCode == Keys.Down || e.KeyCode == Keys.Left || e.KeyCode == Keys.Right || e.KeyCode == Keys.LShiftKey || e.KeyCode == Keys.RShiftKey || e.KeyCode == Keys.Shift || e.KeyCode == Keys.ShiftKey || e.KeyCode == Keys.Select || e.KeyCode == Keys.Control || e.KeyCode == Keys.ControlKey)
m_fOkToUpdateAutoComplete = false;
else
m_fOkToUpdateAutoComplete = true;
}
catch (Exception)
{
}
}
ConcurrentBag<Task> tasks = new ConcurrentBag<Task>();
CancellationTokenSource tokenSource = new CancellationTokenSource();
private IList<CancellationTokenSource> tokenSources = new List<CancellationTokenSource>();
private void cmbSearch_KeyUp(object sender, KeyEventArgs e)
{
try
{
if (e.KeyCode == Keys.Up || e.KeyCode == Keys.Down)
{
isKeyDownOrKeyUp = true;
}
else
{
isKeyDownOrKeyUp = false;
}
if (m_fOkToUpdateAutoComplete)
{
if (tokenSources.Count > 0)
{
foreach (var cancellationTokenSource in tokenSources)
{
if (!cancellationTokenSource.IsCancellationRequested)
{
cancellationTokenSource.Cancel();
}
}
}
tokenSource = new CancellationTokenSource();
var token = tokenSource.Token;
if (!string.IsNullOrEmpty(cmbSearch.Text))
{
Task t;
t = Task.Factory.StartNew(() => InvokeApi(token), token);
tasks.Add(t);
tokenSources.Add(tokenSource);
}
else
{
cmbSearch.DroppedDown = false;
cmbSearch.DataSource = null;
ClearControls();
}
}
}
catch (Exception ex)
{
// MessageBox.Show(ex.Message);
}
}
private void InvokeApi(CancellationToken ct)
{
try
{
var _with1 = cmbSearch;
m_sLastSearchedFor = _with1.Text;
this.UseWaitCursor = true;
// Was cancellation already requested?
if (ct.IsCancellationRequested == true)
{
ct.ThrowIfCancellationRequested();
}
var search = CapturePlus.Find(m_sLastSearchedFor, "").ToList();
//search.Insert(0, new MatchingAddress() {AddressId=string.Empty,Criteria=string.Empty,Text=string.Empty });
// Was cancellation already requested?
if (ct.IsCancellationRequested == true)
{
ct.ThrowIfCancellationRequested();
}
this.UseWaitCursor = false;
if (search.Count > 0)
{
cmbSearch.DataSource = search;
cmbSearch.DisplayMember = "Text";
cmbSearch.ValueMember = "IdAndCrieria";
cmbSearch.DroppedDown = true;
cmbSearch.SelectedIndex = -1;
cmbSearch.Text = m_sLastSearchedFor;
cmbSearch.SelectionStart = cmbSearch.Text.Length;
cmbSearch.AutoCompleteMode = AutoCompleteMode.None;
}
else
{
cmbSearch.DroppedDown = false;
cmbSearch.DataSource = null;
cmbSearch.Text = m_sLastSearchedFor;
cmbSearch.SelectionStart = cmbSearch.Text.Length;
ClearControls();
}
}
catch (OperationCanceledException can)
{
this.UseWaitCursor = false;
cmbSearch.DroppedDown = false;
cmbSearch.DataSource = null;
cmbSearch.Text = m_sLastSearchedFor;
cmbSearch.SelectionStart = cmbSearch.Text.Length;
ClearControls();
}
catch (Exception e)
{
this.UseWaitCursor = false;
}
}
private void cmbSearch_SelectedIndexChanged(object sender, EventArgs e)
{
try
{
if (cmbSearch.SelectedIndex >= -1)
{
if (isKeyDownOrKeyUp)
return; // Disable selection on KeyUp and Keydown.
var id = "";
var criteria = "";
var selectedValue = cmbSearch.SelectedValue;
if (selectedValue != null)
{
char[] separator = new char[] { '_' };
string[] split = selectedValue.ToString().Split(separator);
if (split != null && split.Length > 1)
{
id = split[0];
criteria = split[1];
}
}
if (id != null || criteria != null)
{
if (criteria == "Find")
{
_retrieved = false;
var findAddressWithId = CapturePlus.Find(m_sLastSearchedFor, id).ToList();
if (findAddressWithId.Count > 0)
{
cmbSearch.DataSource = findAddressWithId;
cmbSearch.DisplayMember = "Text";
cmbSearch.ValueMember = "IdAndCrieria";
cmbSearch.DroppedDown = true;
cmbSearch.Text = m_sLastSearchedFor;
cmbSearch.SelectionStart = cmbSearch.Text.Length;
cmbSearch.SelectedIndex = -1;
ClearControls();
}
else
{
cmbSearch.DroppedDown = false;
}
}
else
{
ClearControls();
}
if (criteria == "Retrieve")
{
var retriveAddress = CapturePlus.Retrieve(id).ToList();
try
{
if (retriveAddress.Any())
{
_selectedAddress = retriveAddress.ToArray()[0];
BindDetails(_selectedAddress);
SetAddressToDisplay();
_retrieved = true;
}
else
{
ClearControls();
}
}
catch (Exception)
{
// Log exception.
}
}
else
{
//cmbSearch.DataSource = null;
ClearControls();
}
}
}
else
{
cmbSearch.DataSource = null;
cmbSearch.DroppedDown = false;
ClearControls();
}
}
catch (Exception ex)
{
//MessageBox.Show(ex.Message);
}
}
上面的代码没有按预期工作。
主要问题是
1)。当我使用组合框时,当用户输入第一个项目时,默认情况下会被选中。2).当我将数据源设置为null时,用户的输入正在刷新,这有点令人困惑。3).使用上下箭头在导航列表中选择项目。当选择发生变化时,我们调用API来再次刷新列表。因此,用户无法浏览其他项目。
我认为我没有完全解释清楚,对大多数用户来说可能没有任何意义。对不起。
请告诉我,如果已经有一些自定义控件,可以用来分配动态数据源或一种文本框,它采取输入并显示在组合框样式的列表。
我还会考虑从组合框继承并覆盖事件。您还可以传入要执行的函数,以便在搜索时填充列表。这样以后你就可以重用这个控件,这样测试起来也会更容易。
我个人可能会去Sinatr的建议,创建自己的控件与文本框和列表