Files
netch/NetchLib/SearchComboBox.cs
2020-05-15 20:02:15 +08:00

159 lines
4.3 KiB
C#

using System.Linq;
namespace System.Windows.Forms
{
[System.ComponentModel.DesignerCategory(@"Code")]
public class SearchComboBox : ComboBox
{
public SearchComboBox()
{
AutoCompleteMode = AutoCompleteMode.Suggest;
}
protected override void OnTextChanged(EventArgs e)
{
try
{
if (DesignMode || !string.IsNullOrEmpty(Text) || !Visible) return;
ResetCompletionList();
}
finally
{
base.OnTextChanged(e);
}
}
protected override void OnKeyUp(KeyEventArgs e)
{
try
{
if (DesignMode || e.KeyData == Keys.Up || e.KeyData == Keys.Down) return;
if (e.KeyData == Keys.Return)
{
e.Handled = true;
if (newList.Length > 0 && !newList.Select(o => o.ToString()).Contains(Text))
{
Text = newList[0].ToString();
}
DroppedDown = false;
return;
}
ReevaluateCompletionList();
}
finally
{
base.OnKeyUp(e);
}
}
private void ResetCompletionList()
{
_previousSearchTerm = null;
try
{
SuspendLayout();
var originalList = (object[])Tag;
if (originalList == null)
{
Tag = originalList = Items.Cast<object>().ToArray();
}
if (Items.Count == originalList.Length) return;
while (Items.Count > 0)
{
Items.RemoveAt(0);
}
Items.AddRange(originalList);
}
finally
{
ResumeLayout(true);
}
}
private string _previousSearchTerm;
private object[] newList;
private void ReevaluateCompletionList()
{
try
{
var currentSearchTerm = Text.ToLowerInvariant();
if (currentSearchTerm == _previousSearchTerm) return;
_previousSearchTerm = currentSearchTerm;
try
{
SuspendLayout();
var originalList = (object[])Tag;
if (originalList == null)
{
Tag = originalList = Items.Cast<object>().ToArray();
}
if (string.IsNullOrEmpty(currentSearchTerm))
{
if (Items.Count == originalList.Length) return;
newList = originalList;
}
else
{
newList = originalList.Where(x => x.ToString().ToLowerInvariant().Contains(currentSearchTerm)).ToArray();
}
try
{
while (Items.Count > 0)
{
Items.RemoveAt(0);
}
}
catch
{
try
{
Items.Clear();
}
catch
{
// ignored
}
}
Items.AddRange(newList.ToArray());
}
finally
{
if (currentSearchTerm.Length >= 2 && !DroppedDown)
{
DroppedDown = true;
Cursor.Current = Cursors.Default;
Text = currentSearchTerm;
Select(currentSearchTerm.Length, 0);
}
if (Items.Count > 0)
{
DroppedDown = false;
DroppedDown = true;
}
ResumeLayout(true);
}
}
catch
{
// ignored
}
}
}
}