C#WPF - 从其他类修改ComboBox

时间:2014-04-22 22:38:29

标签: c# wpf combobox

我正在使用Kinect和COM在C#中编写一个小型WPF应用程序,以便与arduino进行通信。

我有一个组合框,用户可以选择他想要使用的端口,我的COM上有一个观察者,每次设备插入/拔出时我想刷新我的组合框。

我的问题是调用该函数是在另一个类中,所以我有一个线程错误

以下是不起作用的代码部分:

namespace Microsoft.Samples.Kinect.SkeletonBasics
{
    using System.IO;
    using System.IO.Ports;
    using System;
    using System.Management;
    using System.Windows;
    using System.Windows.Media;
    using System.Collections.Generic;
    using System.Windows.Controls;
    using Microsoft.Kinect;
    using Microsoft.Kinect.Toolkit;

    public partial class MainWindow : Window
    {

        private WMIReceiveEvent receiveEvent = new WMIReceiveEvent();

        internal static ComboBox comboBox; //Internal static variable so it can be used in static method

        public MainWindow()
        {
            InitializeComponent();
        }

        private void WindowClosing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            using (receiveEvent) {}
        }

        private void ComboBox_Loaded(object sender, RoutedEventArgs e)
        {
            comboBox = Com_ComboBox;
            string[] ports = SerialPort.GetPortNames();
            if (ports.Length == 0)
            {
                Default_Text.Content = "Aucun port détecté";
                comboBox.IsHitTestVisible = false;
                comboBox.Focusable = false;
            }
            else Default_Text.Content = "Arduino sur le port :";

            comboBox.SelectedIndex = 0;

            foreach (string port in ports)
            {
                comboBox.Items.Add(port);
            }
        }

        internal static void Refresh_Coms() //I'm trying to call this function from the other class but I get a thread error
        {
            comboBox.Items.Clear();
            ComboBoxItem Default_Text = (ComboBoxItem) comboBox.ItemContainerGenerator.ContainerFromIndex(0);
            string[] ports = SerialPort.GetPortNames();
            if (ports.Length == 0)
            {
                Default_Text.Content = "Aucun port détecté";
                comboBox.IsHitTestVisible = false;
                comboBox.Focusable = false;
                comboBox.SelectedIndex = 0;
            }
            else Default_Text.Content = "Arduino sur le port :";

            foreach (string port in ports)
            {
                comboBox.Items.Add(port);
            }
        }

        private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {

        }
    }

    public class WMIReceiveEvent : IDisposable
    {
        private ManagementEventWatcher watcherAttach;
        private ManagementEventWatcher watcherDetach;

        public WMIReceiveEvent()
        {
            try
            {
                watcherAttach = new ManagementEventWatcher();
                watcherAttach.EventArrived += Attaching;
                watcherAttach.Query = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 2");
                watcherAttach.Start();

                watcherDetach = new ManagementEventWatcher();
                watcherDetach.EventArrived += Detaching;
                watcherDetach.Query = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 3");
                watcherDetach.Start();
                return;
            }
            catch (ManagementException err)
            {
                MessageBox.Show("An error occurred while trying to receive an event: " + err.Message);
            }
        }

        public void Dispose()
        {
            try
            {
                watcherAttach.Stop();
                watcherDetach.Stop();
                watcherAttach.Dispose();
                watcherDetach.Dispose();
            }
            catch
            {
                MessageBox.Show("An error occurred while trying to close COM event Handler");
            }
        }

        void Attaching(object sender, EventArrivedEventArgs e)
        {
            if (sender != watcherAttach) return;
            Console.WriteLine("Attaching");
            MainWindow.Refresh_Coms(); //I can call the function but the thread can't modify the ComboBox
        }

        void Detaching(object sender, EventArrivedEventArgs e)
        {
            if (sender != watcherDetach) return;
            Console.WriteLine("Detaching");
            MainWindow.Refresh_Coms();
        }

        ~WMIReceiveEvent()
        {
            this.Dispose();
        }
    }
}

我对C#有点新鲜,我在网上搜索过但我找不到一个简单的解决方案,有人可以帮我吗?

1 个答案:

答案 0 :(得分:1)

SynchronizationContext添加到您的WMIReceiveEvent课程中,例如:

public class WMIReceiveEvent : IDisposable
{   
    private readonly SynchronizationContext _syncContext;
    public WMIReceiveEvent(SynchronizationContext syncContext)
    {
        _cyncContext = syncContext;
    }
}

并使用MainWindow.Refresh_Coms(); Send方法调用SynchronizationContext包裹:

_syncContext.Send(o => MainWindow.Refresh_Coms(), null);

最后一件事是创建你的WMIReceiveEvent课程:

private WMIReceiveEvent receiveEvent = new WMIReceiveEvent(SynchronizationContext.Current);
关于SynchronizationContext的

More