【问题标题】:Unable to populate listbox无法填充列表框
【发布时间】:2017-10-31 13:57:18
【问题描述】:

在我的列表框中显示列表时遇到了一些麻烦。 当我在一堂课上拥有一切时,一切似乎都很好,但我不知道为什么它现在不起作用。当单击扫描按钮时,我的应用程序转到另一个类,其中创建了一个新线程来扫描可用的蓝牙设备,并创建了包含这些设备的列表。一旦列表被传递回 Form1 类中的方法,它就不会更新列表框。在调试模式下,我可以看到列表中有项目,但列表框中没有任何内容。如果我从扫描按钮单击方法执行 listBox1.Items.Add("Hello World") ,则列表框会显示项目。我有点卡在这里。我刚刚开始学习 C#,如果有人可以帮助我,我将不胜感激。

public partial class Form1 : Form
{
    int PanelWidth;
    bool PanelCalShow;

    public Form1()
    {
        InitializeComponent();
        PanelWidth = PanelCal.Width;
        PanelCalShow = false;           
    }

    private void button2_Click(object sender, EventArgs e)
    {
        timer1.Start();
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        if (PanelCalShow)
        {
            PanelCal.Width = PanelCal.Width + 10;

            if (PanelCal.Width >= PanelWidth)
            {
                timer1.Stop();
                PanelCalShow = false;
                this.Refresh();
            }
        }
        else
        {
            if (PanelCalShow != true)
            {
                PanelCal.Width = PanelCal.Width - 10;

                if (PanelCal.Width <= 0)
                {
                    timer1.Stop();
                    PanelCalShow = true;
                    this.Refresh();
                }
            }
        }
    }

    // Bluetooth connection
    private void BtnScan_Click(object sender, EventArgs e)
    {
        var instance = new BtCom();
        instance.Scan();   
    }        

    public void LbClientUpdate(List<string> DiscoveredDevices)
    {                        
        listBox1.DataSource = DiscoveredDevices;            
    }        
}

和蓝牙连接类

public class BtCom
{
    public List<string> DiscoveredDevices = new List<string>();
    Guid mUUID = new Guid("00001101-0000-1000-8000-00805F9B34FB");

    public void Scan()
    {            
        Thread bluetoothScanThread = new Thread(new ThreadStart(Scanning));
        bluetoothScanThread.Start();
    }

    BluetoothDeviceInfo[] devices;

    public void Scanning()
    {            
        var form1 = new Form1();

        BluetoothClient client = new BluetoothClient();
        devices = client.DiscoverDevicesInRange();

        foreach (BluetoothDeviceInfo d in devices)
        {
            DiscoveredDevices.Add(d.DeviceName);
        }           
      form1.LbClientUpdate(DiscoveredDevices);
    }
}

【问题讨论】:

  • 你有一个函数LbClientUpdate来设置ListBox的DataSource,但是它不是从任何地方调用的。
  • 您在原始表单上没有看到任何更新的原因是您正在 BtCom 类中创建 Form1 类的新实例,而不是使用原始实例。
  • 嗨,对不起。我正在删除 cmets,并且必须也删除了它。我在 listBox1.DataSource 之后有一个带有“hello world”的消息框,它会像它应该弹出的那样弹出,但列表框中没有任何内容。可能是因为该方法是从不同的线程调用的,因此它也在该线程中执行,并且据我所知,应该从其原始线程中编辑列表框?

标签: c# bluetooth listbox


【解决方案1】:

您在原始表单上没有看到任何更新的原因是您在 BtCom 类中创建了 Form1 类的新实例,而不是使用原始实例。

您可以解决此问题的一种方法是将表单的原始实例通过Scan 方法的参数传递给您的BtClass,然后将其传递给您的Scanning 方法。这样,您将在正在运行的表单的同一实例上调用方法。

这样做的问题是在等待线程完成时您将阻塞 UI(假设您调用 bluetoothScanThread.Join() 来等待线程结果)。

一个稍微不同的解决方案是使用Tasks,使用async 方法,await 结果。

为此,您将让您的scan 方法返回一个Task&lt;List&lt;string&gt;&gt;(这是一个返回代表设备的List&lt;string&gt; 的Task)。

然后在form1 中,您将创建一个async 方法(下面称为GetDatasource),该方法创建BtCom 类的实例,awaits scan 方法,并返回Task&lt;List&lt;string&gt;&gt;。

最后,您还可以将Click 方法设为async 并让它分配等待GetDatasource 方法并在它返回时分配数据源。

通过这种方式,您可以将 BtCon 类与了解有关 Form1 类的任何细节隔离开来,这是一个养成的好习惯,因为您最终会创建更多可重用和独立的代码。

这是代码中所有这些单词的示例:

使scan 方法返回可用于数据源的Task&lt;List&lt;string&gt;&gt;(并让Scanning 返回List&lt;string&gt;)。请注意,该列表现在对扫描方法是私有的。将变量的范围限制在所需的级别是一个很好的做法。:

public class BtCom
{
    Guid mUUID = new Guid("00001101-0000-1000-8000-00805F9B34FB");

    public Task<List<string>> Scan()
    {
        var bluetoothScanTask = Task.Factory.StartNew(Scanning);
        bluetoothScanTask.Wait();
        return bluetoothScanTask;
    }

    private List<string> Scanning()
    {
        BluetoothClient client = new BluetoothClient();
        devices = client.DiscoverDevicesInRange();

        List<string> discoveredDevices = new List<string>();

        foreach (BluetoothDeviceInfo d in devices)
        {
            discoveredDevices.Add(d.DeviceName);
        }

        return discoveredDevices;
    }
}

然后,编写一个 async 方法,该方法将通过创建此类的新实例来获取数据源,并编写 await 以返回该方法。另外,使 Click 方法异步,以便它可以 await 数据源方法:

public partial class Form1 : Form
{
    // Other form code omitted...

    private async void BtnScan_Click(object sender, EventArgs e)
    {
        listBox1.DataSource = await Task.Run(GetDatasource);
    }

    private async Task<List<string>> GetDatasource()
    {
        var btCom = new BtCom();
        List<string> results = await btCom.Scan();
        return results;
    }

现在您的用户可以单击该按钮,并且表单将在扫描发生时继续响应,并且您的列表框将在扫描方法完成时填充。

有关async 和await 的更多信息,请查看您最喜欢的搜索引擎(例如Asynchronous programming 上的此页面)。

【讨论】:

  • 非常感谢您的帮助。今晚下班回家后我会尝试一切。正如我所说,我刚开始使用 C#,或多或少地一起编写代码,所以我非常感谢你的帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-18
相关资源
最近更新 更多