mirror of
https://github.com/netchx/netch.git
synced 2026-03-14 17:43:18 +08:00
179 lines
4.5 KiB
C#
179 lines
4.5 KiB
C#
using System.Linq;
|
|
|
|
namespace System.Windows.Forms
|
|
{
|
|
[System.ComponentModel.DesignerCategory(@"Code")]
|
|
public class SearchComboBox : ComboBox
|
|
{
|
|
public SearchComboBox()
|
|
{
|
|
AutoCompleteMode = AutoCompleteMode.Suggest;
|
|
}
|
|
|
|
|
|
private string prevKeyword;
|
|
|
|
private string Keyword
|
|
{
|
|
get => _keyword;
|
|
set
|
|
{
|
|
prevKeyword = _keyword;
|
|
if (value == null)
|
|
{
|
|
_keyword = null;
|
|
return;
|
|
}
|
|
|
|
if (_keyword == value)
|
|
{
|
|
return;
|
|
}
|
|
|
|
_keyword = value;
|
|
ReevaluateCompletionList();
|
|
}
|
|
}
|
|
|
|
protected override void OnTextChanged(EventArgs e)
|
|
{
|
|
try
|
|
{
|
|
if (string.IsNullOrEmpty(Text))
|
|
{
|
|
if (!IsOriginalItems)
|
|
ResetCompletionList();
|
|
Keyword = null;
|
|
}
|
|
else
|
|
{
|
|
if (AutoFillTag.All(o => o.ToString() != Text))
|
|
{
|
|
Keyword = Text;
|
|
}
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
base.OnTextChanged(e);
|
|
}
|
|
}
|
|
|
|
|
|
private object[] AutoFillTag
|
|
{
|
|
get
|
|
{
|
|
if (Tag == null)
|
|
{
|
|
Tag = Items.Cast<object>().ToArray();
|
|
}
|
|
|
|
return (object[]) Tag;
|
|
}
|
|
}
|
|
|
|
private bool IsOriginalItems => Items.Count == AutoFillTag.Length;
|
|
|
|
public void ResetCompletionList()
|
|
{
|
|
Keyword = null;
|
|
try
|
|
{
|
|
SuspendLayout();
|
|
|
|
if (IsOriginalItems)
|
|
return;
|
|
|
|
Items.Clear();
|
|
Items.AddRange(AutoFillTag);
|
|
}
|
|
finally
|
|
{
|
|
ResumeLayout(true);
|
|
}
|
|
}
|
|
|
|
private static int findFirstDifIndex(string s1, string s2)
|
|
{
|
|
for (var i = 0; i < Math.Min(s1.Length, s2.Length); i++)
|
|
if (s1[i] != s2[i])
|
|
return i;
|
|
|
|
return -1;
|
|
}
|
|
|
|
private object[] _newList;
|
|
private string _keyword;
|
|
|
|
private void ReevaluateCompletionList()
|
|
{
|
|
SuspendLayout();
|
|
var keyword = Keyword.ToLowerInvariant().Trim();
|
|
|
|
var selectionStart = SelectionStart;
|
|
if (selectionStart == Text.Length)
|
|
{
|
|
selectionStart = -1;
|
|
}
|
|
else
|
|
{
|
|
selectionStart = findFirstDifIndex(prevKeyword, Keyword);
|
|
}
|
|
|
|
try
|
|
{
|
|
var originalList = AutoFillTag;
|
|
if (originalList == null)
|
|
{
|
|
Tag = originalList = Items.Cast<object>().ToArray();
|
|
}
|
|
|
|
if (string.IsNullOrEmpty(Keyword))
|
|
{
|
|
ResetCompletionList();
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
_newList = originalList.Where(x => x.ToString().ToLowerInvariant().Contains(keyword)).ToArray();
|
|
}
|
|
|
|
if (_newList.Any())
|
|
{
|
|
Items.Clear();
|
|
Items.AddRange(_newList.ToArray());
|
|
|
|
if (!DroppedDown)
|
|
{
|
|
DroppedDown = true;
|
|
}
|
|
else
|
|
{
|
|
// TODO 预期下拉框高度变长则重新打开下拉框
|
|
}
|
|
|
|
Cursor.Current = Cursors.Default;
|
|
}
|
|
else
|
|
{
|
|
DroppedDown = false;
|
|
Items.Clear();
|
|
}
|
|
|
|
if (selectionStart == -1)
|
|
{
|
|
Select(Text.Length, 0);
|
|
}
|
|
else
|
|
{
|
|
Select(selectionStart + 1, 0);
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
ResumeLayout(true);
|
|
}
|
|
}
|
|
}
|
|
} |