我的应用程序中有一个组合框,其中的项目根据您可以在文本字段中输入的搜索文本异步加载。
这工作正常,但每次更新组合框的数据源时都会自动选择第一项的文本。
这会导致意外的行为,因为我需要让用户输入的搜索文本保留在组合框的文本字段中,直到用户完成选择,并且不会自动用第一个条目覆盖文本。
这是我的代码:
public partial class ProductGroupDescription : UserControl, Interfaces.TabPages.ITabPageProductGroupDescription
{
private Services.IProductGroupDescriptionService _ApplicationService;
public BindingList<ProductGroup> ProductGroups { get; set; } = new BindingList<ProductGroup>();
public string ProductGroupSearchText { get; set; } = string.Empty;
public ProductGroupDescription(Services.IProductGroupDescriptionService applicationService)
{
InitializeComponent();
InitialSetupControls();
_ApplicationService = applicationService;
}
public void InitialSetupControls()
{
var pgBindingSource = new BindingSource();
pgBindingSource.DataSource = ProductGroups;
Cbo_ProductGroup.DataSource = pgBindingSource.DataSource;
Cbo_ProductGroup.DataBindings.Add("Text", ProductGroupSearchText, "");
}
private async void Cbo_ProductGroup_TextChanged(object sender, EventArgs e)
{
if (Cbo_ProductGroup.Text.Length >= 2)
{
ProductGroupSearchText = Cbo_ProductGroup.Text;
Cbo_ProductGroup.SelectedIndex = -1;
bool withStopFlagged = Chk_StopFlag_PGs_Included.Checked;
List<ProductGroup> list = await _ApplicationService.GetProductGroupBySearchString(ProductGroupSearchText, withStopFlagged);
if (list != null && list.Count > 0)
{
ProductGroups.Clear();
list.ForEach(item => ProductGroups.Add(item));
Cbo_ProductGroup.DroppedDown = Cbo_ProductGroup.Items.Count > 0 && Cbo_ProductGroup.Focused;
}
}
}
}
我尝试设置
Cbo_ProductGroup.SelectedIndex = -1
,但它并不能解决我的问题。
我也在 SO 上看到了这一点:防止 System.Window.Forms.ComboBox (C#) 的 AutoSelect 行为
但是这个问题真的没有更简单的解决方案吗?
我现在可以使用它了。 当我删除组合框文本字段的绑定时,它起作用了
Cbo_ProductGroup.DataBindings.Add("Text", ProductGroupSearchText, "");
并将新(旧)值直接设置到组合框的文本字段。
Cbo_ProductGroup.Text = searchText;
在这种情况下,会触发一个新事件
Text_Changed
,因此应用程序具有无限循环。所以我使用了一个属性 (ShouldTextChangedEventBeIgnored
),如果 Text_Changed
事件应该被忽略。
感谢@CaiusJard 在评论中提供的许多提示。
这是我的最终代码:
public partial class ProductGroupDescription : UserControl, Interfaces.TabPages.ITabPageProductGroupDescription
{
private ApplicationLogic.Interfaces.Services.IProductGroupDescriptionService _ApplicationService;
public BindingList<ProductGroup> ProductGroups { get; set; } = new BindingList<ProductGroup>();
public bool ShouldTextChangedEventBeIgnored { get; set; } = false;
public ProductGroupDescription(ApplicationLogic.Interfaces.Services.IProductGroupDescriptionService applicationService)
{
_ApplicationService = applicationService;
InitializeComponent();
InitialSetupControls();
}
public void InitialSetupControls()
{
var pgBindingSource = new BindingSource();
pgBindingSource.DataSource = ProductGroups;
Cbo_ProductGroup.DataSource = pgBindingSource.DataSource;
}
private async Task<List<ProductGroup>> LoadProductGroupItems(string searchText)
{
bool withStopFlagged = Chk_StopFlag_PGs_Included.Checked;
return await _ApplicationService.GetProductGroupBySearchString(searchText, withStopFlagged);
}
private async Task SetProductGroupSearchBoxItems(List<ProductGroup> list, string searchText)
{
await Task.Run(() =>
{
if (list != null && list.Count > 0)
{
ShouldTextChangedEventBeIgnored = true;
Cbo_ProductGroup.Invoke((c) =>
{
ProductGroups.Clear();
list.ForEach(item => ProductGroups.Add(item));
c.DroppedDown = c.Items.Count > 0 && c.Focused;
c.Text = searchText;
c.Select(c.Text.Length, 0);
});
ShouldTextChangedEventBeIgnored = false;
}
});
}
private async void Cbo_ProductGroup_TextChanged(object sender, EventArgs e)
{
try
{
if (Cbo_ProductGroup.Text.Length >= 2 && ShouldTextChangedEventBeIgnored == false)
{
string searchText = Cbo_ProductGroup.Text;
List<ProductGroup> list = await LoadProductGroupItems(Cbo_ProductGroup.Text);
await SetProductGroupSearchBoxItems(list, searchText);
}
}
catch(Exception ex)
{
System.Diagnostics.Trace.Write(ex);
}
}
}
感谢这个解决方案。不过上线了
Cbo_ProductGroup.Invoke((c) =>
{
ProductGroups.Clear();
list.ForEach(item => ProductGroups.Add(item));
c.DroppedDown = c.Items.Count > 0 && c.Focused;
c.Text = searchText;
c.Select(c.Text.Length, 0);
});
我收到错误“无法将匿名方法块转换为类型‘type’,因为它不是委托类型”
如果我尝试使用另一种方法,则会出现此错误“无效的跨线程操作:控件'Cbo_ProductGroup'是从创建它的线程以外的线程访问的。”
我该如何解决这个问题?