Wpf did not update the UI when binding the template Reason: Do not use clear() but use new, why? Who would have thought of this pit?

The UI is not updated when the template is bound. Don’t use clear() to use new.

bindingListSP = new List();//bindingListSP.Clear(); no

using FT_Tools;
using MSFramework. Common;
using NFC_Help;
using System;
using System.Collections.Generic;
using System. ComponentModel;
using System. Management;
using System. Windows;
using WpfDownloadTool;
using static System.Net.Mime.MediaTypeNames;

namespace WpfM20UpdateFW
{
    /// <summary>
    /// Interaction logic of MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        //Sort the serial ports in the order of insertion, regardless of insertion. add new delete nonexistent
        List<string> comListSP = new List<string>();
        List<string> comListAP = new List<string>();
        public USB USBWatcher = new USB();
        private List<DownloadSP1902QualComm> dList = new List<DownloadSP1902QualComm>();
        List<BindingClass> bindingListSP = new List<BindingClass>();
        List<BindingClass> bindingListAP = new List<BindingClass>();
        private int AutoTask =1;
        private int mode = 1;
        private int MaxDeviceCount = 8;
        private int Speech = 1;
        public MainWindow()
        {
            InitializeComponent();
            this.Title += System.IO.File.GetLastWriteTime(this.GetType().Assembly.Location);

            init();
            setDownloadList();
            USBWatcher.AddUSBEventWatcher(USBEventHandler, USBEventHandler, new TimeSpan(0, 0, 1));
        }
        public void init()
        {
            logText.Text = "";
            bindingListSP = new List<BindingClass>();//bindingListSP.Clear(); no
            bindingListAP = new List<BindingClass>(); //bindingListAP. Clear();
            DownloadSP1902QualComm.SP = IniFile.GetPrivateProfileInt(DownloadSP1902QualComm.configAppName, "SP", 1, IniFile.m_FileName);
            DownloadSP1902QualComm.AP = IniFile.GetPrivateProfileInt(DownloadSP1902QualComm.configAppName, "AP", 1, IniFile.m_FileName);
            DownloadSP1902QualComm.timeoutSecond = IniFile.GetPrivateProfileInt(DownloadSP1902QualComm.configAppName, "TimeoutSecond", 20, IniFile.m_FileName);
            DownloadSP1902QualComm.SP_SigFile = IniFile.ReadString(DownloadSP1902QualComm.configAppName, DownloadSP1902QualComm.SigFilePath, ""); //Resource number or local file name
            DownloadSP1902QualComm.SP_RSAKeyFile = IniFile.ReadString(DownloadSP1902QualComm.configAppName, DownloadSP1902QualComm.RSAKeyPath, ""); //Resource number or local file name
            DownloadSP1902QualComm.AP_File = IniFile.ReadString(DownloadSP1902QualComm.configAppName, DownloadSP1902QualComm.APPath, "");
            DownloadSP1902QualComm.AutoComCount = IniFile.GetPrivateProfileInt(DownloadSP1902QualComm.configAppName, "AutoComCount", 1, IniFile.m_FileName);
            AutoTask = IniFile.GetPrivateProfileInt(DownloadSP1902QualComm.configAppName, "AutoTask", 1, IniFile.m_FileName);
            MaxDeviceCount = IniFile.GetPrivateProfileInt(DownloadSP1902QualComm.configAppName, "MaxDeviceCount", 8, IniFile.m_FileName);
            Speech=IniFile.GetPrivateProfileInt(DownloadSP1902QualComm.configAppName, "Speech", 1, IniFile.m_FileName);
            mode = IniFile.GetPrivateProfileInt(DownloadSP1902QualComm.configAppName, "mode", 1, IniFile.m_FileName);
            Log("MaxDeviceCount=" + MaxDeviceCount);
            Log("AutoCom=" + DownloadSP1902QualComm.AutoComCount);
            Log("SP=" + DownloadSP1902QualComm.SP);
            Log("AP=" + DownloadSP1902QualComm.AP);
            Log("SP_SigFile=" + DownloadSP1902QualComm.SP_SigFile);
            Log("SP_RSAKeyFile=" + DownloadSP1902QualComm.SP_RSAKeyFile);
            Log("AP_File=" + DownloadSP1902QualComm.AP_File);
            //Set the progress bar interface update
            for (int i = 0; i < MaxDeviceCount; i ++ )
            {
                bindingListSP.Add(new BindingClass() { Name = IniFile.ReadString(DownloadSP1902QualComm.configAppName, "SP_COM" + (i + 1), "" + (i + 1)) });
                bindingListAP.Add(new BindingClass() { Name = IniFile.ReadString(DownloadSP1902QualComm.configAppName, "AP_COM" + (i + 1), "" + (i + 11)) });
            }
            myListBoxSP.ItemsSource = bindingListSP;
            myListBoxAP.ItemsSource = bindingListAP;


            //load task
            dList. Clear();
            for (int i = 0; i < bindingListSP. Count; i ++ )
            {
                dList.Add(new DownloadSP1902QualComm(Log, bindingListSP[i].Name, bindingListAP[i].Name, i));
                dList[i].OnUpdateUI + = OnUpdateUI;
            }
        }

        private void USBEventHandler(Object sender, EventArrivedEventArgs e)
        {
            // not yet implemented
            var watcher = sender as ManagementEventWatcher;
            watcher.Stop();
            // Refresh device information
            if (e.NewEvent.ClassPath.ClassName == "__InstanceCreationEvent")
            {
                Log("Device Arrived");
                setDownloadList();
                SaveCom();//Save only when inserting
            }
            else if (e.NewEvent.ClassPath.ClassName == "__InstanceDeletionEvent")
            {
                Log("Device Removed");
                setDownloadList();
            }
            // Business code, try not to take too long logic, so as not to affect the monitoring of events
            watcher. Start();
        }

        private void AutoTaskDownload()
        {
            if (AutoTask == 1 & amp; & amp; DownloadSP1902QualComm.SP > 0 & amp; & amp; DownloadSP1902QualComm.AP>0)
            {
                for (int i = 0; i < bindingListAP.Count; i ++ )
                {
                    if (!MySerialPort.isComExist(Log, bindingListAP[i].Name))
                    {
                        if (bindingListAP[i].ProgressValue == 100)
                        {
                            Dispatcher.Invoke((Action)(() => { logText.Text = ""; }));//Clear and restore
                            if (dList[i]. thread_isRunning == false)
                            {
                                Log("AutoTask" + (i + 1));
                                dList[i].Start();
                            }
                        }
                    }
                }
            }
        }

        private void AutoSortCom(List<string> comList,ref List<string> sortList)
        {
            try
            {
                if (comList. Count == 0) { sortList. Clear(); return; }
                foreach (string com in comList)
                {
                    if (!sortList.Contains(com)) //add new
                    {
                        sortList. Add(com);
                    }
                }
                for (int i = 0; i < sortList. Count;)
                {
                    if (!comList.Contains(sortList[i])) //Delete does not exist
                    {
                        sortList. Remove(sortList[i]);
                    }
                    else
                    {
                        i + + ;
                    }
                }
            }
            catch (Exception e) {
                Log(e. StackTrace);
            }
    
        }
        //Display the number of progress bars according to the number of serial ports
        private void setDownloadList()
        {
            AutoSortCom(DownloadSP1902QualComm.GetComNameListSP(Log), ref comListSP);//Several devices display several display bars
            if (comListSP.Count <= DownloadSP1902QualComm.AutoComCount)
            {
                for (int i = 0; i < comListSP.Count; i ++ )
                {
                    if (dList.Count > 0) { dList[i].spCom = comListSP[i]; }
                    if (bindingListAP.Count > i) { bindingListSP[i].Name = comListSP[i]; }//Refresh
                }
            }

            AutoSortCom(DownloadSP1902QualComm.GetComNameListAP(Log), ref comListAP);//Several devices display several display bars
            //Log("AutoComCount=" + AutoComCount);
            if (comListAP.Count <= DownloadSP1902QualComm.AutoComCount) //Only valid for one
            {
                for (int i = 0; i < comListAP.Count; i ++ )
                {
                    if (dList.Count > 0) { dList[i].apCom = comListAP[i]; }
                    if (bindingListAP.Count > i) { bindingListAP[i].Name = comListAP[i]; }//Refresh
                    //Log(i + " " + bindingListAP[i].Name + " " + comListAP[i]);
                }
            }
            Log("SP quantity:" + comListSP.Count + "AP quantity:" + comListAP.Count);
        }
        private void SaveCom()
        {
            if (comListAP.Count == DownloadSP1902QualComm.AutoComCount)//All devices are plugged in, save
            {
                for (int i = 0; i < comListSP.Count; i ++ )
                {
                    IniFile.WriteString(DownloadSP1902QualComm.configAppName, "SP_COM" + (i + 1), comListSP[i]);
                }
                for (int i = 0; i < comListAP.Count; i ++ )
                {
                    IniFile.WriteString(DownloadSP1902QualComm.configAppName, "AP_COM" + (i + 1), comListAP[i]);
                }
                Log("Save com success");
            }
        }
     
        
        private void Log(string log)
        {
      
            //Dispatcher.BeginInvoke((Action)(() => { //Asynchronous
            Dispatcher.Invoke((Action)(() => { //synchronization
                try
                {
                    MyLog.MyLog.WriteLogs(MyLog.MyLog.fileName, "", log);
                    if (mode == 1 & amp; & amp; logText. Text. Length > 5000)
                    {
                        logText.Text = "";
                        //logText.Text = logText.Text.Substring(logText.Text.Length - 100); //clear
                    }
                    logText.Text + = log + "\r\\
";
                    //logText.SelectionStart = logText.Text.Length;
                    logText.ScrollToEnd();
                }
                catch { }
            }));
        }
        private void Window_Closed(object sender, EventArgs e)
        {
            if (dList != null)
            {
                foreach (var d in dList)
                {
                    d. Stop();
                }
            }
            MyAPI. killProcess("ISPGui");
        }

        private void Button_Click_ap(object sender, RoutedEventArgs e)
        {
            var openFileDialog = new Microsoft.Win32.OpenFileDialog()
            {
                Filter = "F200 F600 AP|*.mbn|F100 AP|*.txt|F200-A F210 AP|*.pac",
                Multiselect = false
            };
            if (openFileDialog. ShowDialog()==true)
            {
                Log("AP_File=" + openFileDialog. FileName);
                IniFile.WritePrivateProfileString(DownloadSP1902QualComm.configAppName, DownloadSP1902QualComm.APPath, DownloadSP1902QualComm.AP_File = openFileDialog.FileName, IniFile.m_FileName);
            }
        }

        private void Button_Click_sp_sig(object sender, RoutedEventArgs e)
        {
            // cannot be modified at runtime
            for (int i = 0; i < bindingListSP. Count; i ++ )
            {
                if (dList[i]. thread_isRunning == true)
                {
                    Log("There are unfinished tasks that cannot be edited.");
                    return;
                }
            }
            SettingsWindow window = new SettingsWindow();
            bool? b = window. ShowDialog();
            init(); //restart


            //var openFileDialog = new Microsoft.Win32.OpenFileDialog()
            //{
            // Filter = "SP File|*.SIG|F100 SP|*.hex",
            // Multiselect = false
            //};
            //if (openFileDialog. ShowDialog() == true)
            //{
            // Log("SP_SigFile=" + openFileDialog.FileName);
            // IniFile.WritePrivateProfileString(DownloadSP1902QualComm.configAppName, DownloadSP1902QualComm.SigFilePath, DownloadSP1902QualComm.SP_SigFile = openFileDialog.FileName, IniFile.m_FileName);
            //}

            //folder
            //var dialog = new System.Windows.Forms.FolderBrowserDialog()
            //{
            // Description = "Please select SP File path"
            //};

            //if( dialog. ShowDialog() == System. Windows. Forms. DialogResult. OK)
            //{
            // Log("SP_SigFile=" + dialog.SelectedPath);
            // IniFile.WritePrivateProfileString(configAppName, SigFilePath, SP_SigFile = dialog.SelectedPath, IniFile.m_FileName);
            //}
        }
        private void Button_Click_sp_rsa(object sender, RoutedEventArgs e)
        {
            var openFileDialog = new Microsoft.Win32.OpenFileDialog()
            {
                Filter = "SP File|*.RSA",
                Multiselect = false
            };
            if (openFileDialog. ShowDialog() == true)
            {
                Log("SP_RSAKeyFile=" + openFileDialog. FileName);
                IniFile.WritePrivateProfileString(DownloadSP1902QualComm.configAppName, DownloadSP1902QualComm.RSAKeyPath, DownloadSP1902QualComm.SP_RSAKeyFile = openFileDialog.FileName, IniFile.m_FileName);
            }
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            download. IsEnabled = false;
            MyAPI.speech(download.Content.ToString(), Speech);
            logText.Text = ""; //Clear and restore
            for (int i = 0; i < bindingListSP. Count; i ++ )
            {
                if (dList[i]. thread_isRunning == false)
                {
                    dList[i].Start();
                }
            }
        }


        private void Window_Loaded(object sender, RoutedEventArgs e2)
        {
      
        }

        private void OnUpdateUI(MessageType type, int index, int value, bool result)
        {
            if (type == MessageType. SP_Progress)
            {
                if (value == 0)
                {
                    bindingListSP[index].ProgressValue = value;
                    bindingListSP[index].ProgressForeground = System.Windows.Media.Brushes.CornflowerBlue;
                }
                else if (value == 100)
                {
                    bindingListSP[index].ProgressValue = value;
                    bindingListSP[index].ProgressForeground = (result ? System.Windows.Media.Brushes.Green : System.Windows.Media.Brushes.Red);
                }
                else {
                    if (bindingListSP[index].ProgressValue > 90) { bindingListSP[index].ProgressValue = 50; } else { bindingListSP[index].ProgressValue + + ; }
                }
            }
            else if (type == MessageType. AP_Progress)
            {

                if (value == 0)
                {
                    bindingListAP[index].ProgressValue = value;
                    bindingListAP[index].ProgressForeground = System.Windows.Media.Brushes.CornflowerBlue;
                }
                else if (value == 100)
                {
      
                    bindingListAP[index].ProgressValue = value;
                    bindingListAP[index].ProgressForeground = (result ? System.Windows.Media.Brushes.Green : System.Windows.Media.Brushes.Red);
                }
                else
                {
                    if (bindingListAP[index].ProgressValue > 90) { bindingListAP[index].ProgressValue = 50; } else { bindingListAP[index].ProgressValue + + ; }
                }
            }
            else if (type == MessageType. FINISH)
            {
                Dispatcher.Invoke((Action)(() => { download.IsEnabled = true; }));
                MyAPI. speech((1 + index) + (result ? " Pass" : " Fail"), Speech);
            }
        }
    }
    public class DownloadProgress
    {
        public string Name { get; set; }//serial port
    }
}

The bound variable needs to be updated, and the attribute change event is called when set

using System. ComponentModel;
using System.Windows.Media;

namespace WpfDownloadTool
{
    //Used for variable synchronization to update the information on the interface
    public class BindingClass : INotifyPropertyChanged
    {

        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, e);
        }



        private string _Name; //Serial port number, etc. are displayed on the progress bar
        public string Name
        {
            get { return _Name; }
            set
            {
                if (value != _Name)
                {
                    _Name = value;
                    OnPropertyChanged(new PropertyChangedEventArgs("Name")); //Is the bound variable Path name <Binding Path="Name"/>
                }
            }
        }

        private int _ProgressValue; //progress bar value
        public int ProgressValue
        {
            get { return _ProgressValue; }
            set
            {
                if (value != _ProgressValue)
                {
                    _ProgressValue = value;
                    OnPropertyChanged(new PropertyChangedEventArgs("ProgressValue"));// not ProgressBar Name
                }
            }
        }
        private Brush _ProgressForeground; //Progress bar color
        public Brush Progress Foreground
        {
            get { return _ProgressForeground; }
            set
            {
                if (value != _ProgressForeground)
                {
                    _ProgressForeground = value;
                    OnPropertyChanged(new PropertyChangedEventArgs("ProgressForeground"));// not ProgressBar Name
                }
            }
        }
    }
}