Search code examples
c#wpfmvvmtimeticker

ObservableCollection updating List


I am new in WPF and MVVM also. I'm searching for USB devices in my program. But if I connect a new device, it is required to restart program to became visible.

How to do it, that refresh immediately.

Currently I have in my class in which I search device this:

public List<Devices> devices = new List<Devices>();

    public void FindDevices() // spremeni v public bool da dobis feedback 
    {


        _deviceList = HidDevices.Enumerate(VendorID, ProductID).ToArray();

...     devices.Add(new Devices()
            {
                DeviceId = nod + 1,
                ManufacturerId = deviceManufacturerstring[nod],
                ProductId = deviceProductstring[nod],
                SerialNumberId = deviceSNstring[nod],
                HardwareVersionId = "test4",
                FirmwareVersionId = "test5",
                DateOfManufaturedId = "test6"

            });

On hole for loop I add device to List. I need for loop because I read some data from each device.

I later add this devices in List in ViewModel:

public class Windows1ViewModel : ViewModelBase
{
    public ObservableCollection<Devices> devfuck { get; protected set; }
    List<Devices> _devicelist;

    public List<Devices> Devices
    {
        get { return _devicelist; }
        set { _devicelist = value; }
    }

    public Windows1ViewModel()
    {

        USBmiddleware cs = new USBmiddleware();
        cs.FindDevices();


        devfuck = new ObservableCollection<Devices>();


        foreach (var item in cs.devices)
        {
            devfuck.Add(item);
        }

        List<Devices> keks = cs.devices;



        NotifyPropertyChanged("devfuck");
    }


    public List<Devices> lvdevices
    {
        get { return _devicelist; }
        set { _devicelist = value; }
    }

What to change? Where to add INotifyPropertyChanged? Or how to solve my problem? Please for help. Thanks!

My ViewModelBase

public class ViewModelBase : INotifyPropertyChanged, IDisposable
{


    protected ViewModelBase()
    {
    }



    #region DisplayName


    public virtual string DisplayName { get; protected set; }

    #endregion // DisplayName

    #region Debugging Aides


    [Conditional("DEBUG")]
    [DebuggerStepThrough]
    public void VerifyPropertyName(string propertyName)
    {
        // Verify that the property name matches a real,  
        // public, instance property on this object.
        if (TypeDescriptor.GetProperties(this)[propertyName] == null)
        {
            string msg = "Invalid property name: " + propertyName;

            if (this.ThrowOnInvalidPropertyName)
                throw new Exception(msg);
            else
                Debug.Fail(msg);
        }
    }


    protected virtual bool ThrowOnInvalidPropertyName { get; private set; }



    public event PropertyChangedEventHandler PropertyChanged;


    /// <param name="propertyName">The property that has a new value.</param>
    protected virtual void NotifyPropertyChanged(string propertyName)
    {
        this.VerifyPropertyName(propertyName);

        PropertyChangedEventHandler handler = this.PropertyChanged;
        if (handler != null)
        {
            var e = new PropertyChangedEventArgs(propertyName);
            handler(this, e);
        }
    }

    protected virtual void NotifyPropertyChangedAll(object inOjbect)
    {
        foreach (PropertyInfo pi in inOjbect.GetType().GetProperties())
        {
            NotifyPropertyChanged(pi.Name);
        }
    }
    public virtual void Refresh()
    {
        NotifyPropertyChangedAll(this);
    }



    public void Dispose()
    {
        this.OnDispose();
    }

    /// <summary>
    /// Child classes can override this method to perform 
    /// clean-up logic, such as removing event handlers.
    /// </summary>
    protected virtual void OnDispose()
    {
    }



    ~ViewModelBase()
    {
        string msg = string.Format("{0} ({1}) ({2}) Finalized", this.GetType().Name, this.DisplayName, this.GetHashCode());
        System.Diagnostics.Debug.WriteLine(msg);
    }


}

Solution

  • You can do it by using a timer which gets called ever so often (as needed). Of course it would be sexier if you could do this using event management...

    Thankfully there is a way to do this :

    var watcher = new ManagementEventWatcher();
    var query = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent WHERE       EventType = 2");
    watcher.EventArrived += new EventArrivedEventHandler(watcher_EventArrived);
    watcher.Query = query;
    watcher.Start();
    

    as stated here: Detecting USB drive insertion and removal using windows service and c#

    You can then subscribe to the event and invoke your

    FindDevices()
    

    From there.