WPF ComboBox 在 Text 属性更改时从数据库更新其 ItemsSource
我希望在表单上有一个 ComboBox
控件,用于在用户键入时搜索投资列表。如果我在启动时缓存数据库中的整个投资集合(目前大约有 3,000 个项目),我可以轻松地做到这一点,但如果没有必要,我宁愿不这样做。
我试图实现的行为是:
- 用户在可编辑的组合框中键入文本。
- 当用户输入每个字符时,就会触发数据库搜索功能,每次连续击键都会缩小搜索结果的范围。
- 当搜索结果更新时,下拉面板将打开并显示相关匹配项
我尝试将 ComboBox
的 Text
属性绑定到 InvestmentName
我的 ViewModel
上的(字符串)属性,以及 ComboBox
的 ItemsSource
属性到 InvestmentList
(通用列表)我的 ViewModel
上的属性。当我执行此操作时,Text
属性会从 ItemsSource
自动完成,但下拉列表显示为空。
我已经能够使用堆叠在 ListBox
顶部的 TextBox
来实现这些结果,但它不是很优雅,而且占用了更多的屏幕空间。我还能够让它与堆叠在 ComboBox
顶部的 TextBox
一起使用,尽管 ComboBox
在当存在有效的搜索项时,IsDropDownOpen
属性设置为“true”。为此使用两个控件在视觉上也不太令人愉快。
我觉得我已经很接近让它按照我想要的方式工作了,但是有一些事情让我困惑。
该控件的 XAML 为:
<ComboBox Height="23" Width="260" IsSynchronizedWithCurrentItem="True" HorizontalAlignment="Left"
ItemsSource="{Binding InvestmentList}" DisplayMemberPath="FullName"
IsDropDownOpen="{Binding DoShowInvestmentList}"
ItemsPanel="{DynamicResource ItemsTemplate}" IsEditable="True"
Text="{Binding Path=InvestmentName, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" />
相关的 ViewModel
属性为:
private bool _doShowInvestmentList;
public bool DoShowInvestmentList
{
get { return _doShowInvestmentList; }
set { if (_doShowInvestmentList != value) { _doShowInvestmentList = value; RaisePropertyChanged("DoShowInvestmentList"); } }
}
private List<PFInvestment> _investmentList;
public List<PFInvestment> InvestmentList
{
get { return _investmentList; }
set { if (_investmentList != value) { _investmentList = value; RaisePropertyChanged("InvestmentList"); } }
}
private string _investmentName;
public string InvestmentName
{
get { return _investmentName; }
set
{
if (_investmentName != value)
{
_investmentName = value;
this.InvestmentList = DataAccess.SearchInvestmentsByName(value).ToList();
if (this.InvestmentList != null && this.InvestmentList.Count > 0)
this.DoShowInvestmentList = true;
else
this.DoShowInvestmentList = false;
RaisePropertyChanged("InvestmentName");
}
}
}
我对此进行了大量研究,但尚未找到答案。
I would like to have a ComboBox
control on a form which will be used to search a list of investments as the user types. I can do this easily if I cache the entire collection of investments from the database on startup (currently 3,000 or so items), but I would prefer to not do that if it isn't necessary.
The behavior that I am trying to implement is:
- The user types text into the editable ComboBox.
- As the user enters each character, the database search function is triggered, narrowing down the search results with each successive keystroke.
- As the search results are updated, the dropdown panel opens and displays the relevant matches
I have tried binding the Text
property of the ComboBox
to the InvestmentName
(string) property on my ViewModel
, and the ItemsSource
property of the ComboBox
to the InvestmentList
(generic List) property on my ViewModel
. When I do this, the Text
property auto-completes from the ItemsSource
, however the dropdown appears empty.
I have been able to achieve these results using a TextBox
stacked on top of a ListBox
, but it isn't very elegant and it takes up more screen real estate. I've also been able to get it to work with a TextBox
stacked on top of a ComboBox
, although the ComboBox
steals the focus when the IsDropDownOpen
property is set to "true" when there are valid search items. It also isn't very visually pleasing to use two controls for this.
I feel like I'm really close to getting it to work the way I want it to, but there is something which eludes me.
The XAML for this control is:
<ComboBox Height="23" Width="260" IsSynchronizedWithCurrentItem="True" HorizontalAlignment="Left"
ItemsSource="{Binding InvestmentList}" DisplayMemberPath="FullName"
IsDropDownOpen="{Binding DoShowInvestmentList}"
ItemsPanel="{DynamicResource ItemsTemplate}" IsEditable="True"
Text="{Binding Path=InvestmentName, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" />
The relevant ViewModel
properties are:
private bool _doShowInvestmentList;
public bool DoShowInvestmentList
{
get { return _doShowInvestmentList; }
set { if (_doShowInvestmentList != value) { _doShowInvestmentList = value; RaisePropertyChanged("DoShowInvestmentList"); } }
}
private List<PFInvestment> _investmentList;
public List<PFInvestment> InvestmentList
{
get { return _investmentList; }
set { if (_investmentList != value) { _investmentList = value; RaisePropertyChanged("InvestmentList"); } }
}
private string _investmentName;
public string InvestmentName
{
get { return _investmentName; }
set
{
if (_investmentName != value)
{
_investmentName = value;
this.InvestmentList = DataAccess.SearchInvestmentsByName(value).ToList();
if (this.InvestmentList != null && this.InvestmentList.Count > 0)
this.DoShowInvestmentList = true;
else
this.DoShowInvestmentList = false;
RaisePropertyChanged("InvestmentName");
}
}
}
I've done a fair bit of research on this, but I haven't quite found the answer yet.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
查看我在 CodeProject 上写的这篇精彩文章:)
可重用的 WPF 自动完成文本框< /a>
查看最后的 Google suggest 示例,它与您需要的类似,其中每个按键都会触发对服务器的另一个查询。
Check out this great article on CodeProject by... me :)
A Reusable WPF Autocomplete TextBox
Look towards the end for the Google suggest example, it is similar to what you need, where every keypress triggers another query to the server.