WPF ComboBox 在 Text 属性更改时从数据库更新其 ItemsSource

发布于 2024-08-16 02:05:46 字数 2632 浏览 2 评论 0原文

我希望在表单上有一个 ComboBox 控件,用于在用户键入时搜索投资列表。如果我在启动时缓存数据库中的整个投资集合(目前大约有 3,000 个项目),我可以轻松地做到这一点,但如果没有必要,我宁愿不这样做。

我试图实现的行为是:

  • 用户在可编辑的组合框中键入文本。
  • 当用户输入每个字符时,就会触发数据库搜索功能,每次连续击键都会缩小搜索结果的范围。
  • 当搜索结果更新时,下拉面板将打开并显示相关匹配项

我尝试将 ComboBoxText 属性绑定到 InvestmentName我的 ViewModel 上的(字符串)属性,以及 ComboBoxItemsSource 属性到 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

余生一个溪 2024-08-23 02:05:46

查看我在 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文