【问题标题】:How can I fill a ComboBox when GotFocus event is triggered?触发 GotFocus 事件时如何填充 ComboBox?
【发布时间】:2021-06-09 08:34:26
【问题描述】:

我想在 GotFocus 事件触发时填充 ComboBox。 我试图在 GotFocus 事件中填充我的 ComboBox,但它似乎不起作用。 项目在下拉菜单中可见,但当我想选择其中一个时,集合被清除

点击组合框:

尝试选择第一项:

这是我的代码:

Private Sub agence_GotFocus(sender As Object, e As RoutedEventArgs) Handles agence.GotFocus
    strsql = "Select age_cpt, age_abrege + ' ' + age_nom as age_abregenom from gen_agence where age_soc = " & societe.SelectedValue
    Dim da As New SqlDataAdapter(strsql, connSQLServer)
    Dim ds As New DataSet()
    da.Fill(ds, "t")
    agence.ItemsSource = ds.Tables("t").DefaultView
    agence.DisplayMemberPath = "age_abregenom"
    agence.SelectedValuePath = "age_cpt"
End Sub

我该如何管理?

我不想使用 MVVM。

【问题讨论】:

  • “我不想使用 MVVM。” - 为什么? MVVM 是一个典型的 WPF 实现。很多事情在这种模式之外实现起来要困难得多。
  • 显示与您的问题相关的当前实现(XAML 和 Sharp)的代码。
  • @EldHasp 我知道,但我需要将 VBA 应用程序迁移到 WPF VB.Net。所以我想尽可能的保留现有的代码。
  • @EldHasp 我更新了我的问题并添加了一些代码
  • 我无法重现您的问题。对字符串数组comboBox.ItemsSource ="First Second Third".Split(); 的源进行了最简单的赋值。在表赋值后设置断点(在agence.DisplayMemberPath = ... 行)并检查该表的内容。也许你把它空了?

标签: c# .net wpf vb.net xaml


【解决方案1】:

问题是这个事件会触发多次。
下面我将在 Sharpe 中展示一段演示代码(我的 Studio 中没有加载 VB.Net),但是代码很简单,你应该在 BASIC 中自己重复一遍,没有任何问题。

        private void OnGotFocus(object sender, RoutedEventArgs e)
        {
            Debug.WriteLine(++eventCount);
            ComboBox comboBox = (ComboBox)sender;

            // Try the second option by excluding the following line
            if (comboBox.ItemsSource == null)
                comboBox.ItemsSource = "First,Second,Third".Split(',');
        }

代码应检查 null 以免重新连接集合。
注释掉这一行将重现您的问题。
在启动执行并尝试选择一个项目后,您将在“输出”窗口中看到该事件已发生多次。

看起来在扩展时更改列表会以某种方式破坏 ComboBox 内部绑定的逻辑。

有几种方法可以解决这个问题,但为此我们需要知道为什么选择元素的这种初始化 - 当焦点在它上面时。

几种方式:

  1. 在分配新集合之前清空源。
        private void OnGotFocus(object sender, RoutedEventArgs e)
        {
            Debug.WriteLine(++eventCount);
            ComboBox comboBox = (ComboBox)sender;

            comboBox.ItemsSource = null;
            comboBox.ItemsSource = "First,Second,Third".Split(',');
        }
  1. 在加载 ComboBox 时设置一次集合。
        <ComboBox Loaded="OnLoaded"/>
        private void OnLoaded(object sender, RoutedEventArgs e)
        {
            Debug.WriteLine(++eventCount);
            ComboBox comboBox = (ComboBox)sender;

            comboBox.ItemsSource = "First,Second,Third".Split(',');
        }

其他实施选项也是可能的,但我需要了解有关您的任务的更多详细信息,以便选择最好的方法。

回答附加问题:

在分配新集合之前清空源是个好主意。现在我可以将鼠标移到下拉菜单中的值上。但是,当我选择一个值时,该字段会被清除。

如果不是字符串数组,则可以清除选择。 当您进入事件时,您每次都重新创建表格。 而这些表的行,虽然内容相同,但不会被认为是同一个实例。 你从一个表中选择了一行,然后你重写了源,新的源没有这一行。 选择被重置。

我已经在上面写过,为了选择最佳解决方案,我需要你的问题的更多细节。

您选择初始化列表的方式非常不寻常。 每次在 ComboBox 中工作时,都会对数据库进行三到四次查询。 我从来没有遇到过这样的实现,我不明白它的含义。

解释你为什么需要这个?

【讨论】:

  • 在分配新集合之前清空源是个好主意。现在我可以将鼠标移到下拉菜单中的值上。但是,当我选择一个值时,该字段会被清除。
【解决方案2】:

我找到了一种方法来做我想做的事:使用DropDownOpened 事件而不是GotFocus

Private Sub agence_DropDownOpened(sender As Object, e As EventArgs) Handles agence.DropDownOpened
        '... Fill the ComboBox
End Sub

GotFocus 事件中填写ComboBox 在VBA 中有效,但在VB.Net 中无效。

在 VB.Net 中,我无法使用 GotFocus,因为该事件被多次触发。它在以下情况下触发:

  • 我打开ComboBox
  • 我将鼠标移到项目上
  • 我选择了一个项目

此外,这可能会触发 stackoverflow 异常。

我知道在打开它之前最好填写ComboBox。 我正在进行应用程序迁移过程,无法更改整个代码结构。

就我而言,使用DropDownOpened 事件是最好的选择。

感谢帮助我找到解决方案的人。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-03
    • 1970-01-01
    相关资源
    最近更新 更多