iT邦幫忙

1

C# 委派 ui listbox無法使用問題

如題

void _MainLoop(object sender, System.Timers.ElapsedEventArgs e)
        {
            float Value;
            if (!WebAccessFunction.GetTagValue(strTag_Name, out Value))
            {
                #region 委派 textbox
                UpdateUI("讀取Tag失敗", listBox);
                #endregion

                Thread.Sleep(1000);
            }
            else if (Value == 1)
            {
                #region 委派 textbox
                UpdateUI(DateTime.Now.ToString() + " 火警發生中", listBox);
                #endregion

                if (_EventTimer.Enabled == false)
                {
                    this._EventTimer = new System.Timers.Timer();
                    this._EventTimer.Interval = Convert.ToInt32(time) * 1000;
                    this._EventTimer.Elapsed += new System.Timers.ElapsedEventHandler(_EventLoop);
                    this._EventTimer.Start();
                    if (Flage)
                    {
                        RunUrl();
                        Flage = false;
                    }
                }
            }
            else
            {
                Flage = true;
                UpdateUI("火警點復歸", listBox);
                if (_EventTimer.Enabled)
                    _EventTimer.Stop();
            }
        }

        #region 委派 textbox
        private delegate void UpdateUICallBack(string value, Control ctl);

        private void UpdateUI(string value, Control ctl)
        {
            if (this.InvokeRequired)
            {
                UpdateUICallBack uu = new UpdateUICallBack(UpdateUI);
                this.Invoke(uu, value, ctl);
            }
            else
            {
                ctl.Text = value;
            }
        }
        #endregion

部分code如上
請教各位先進
小弟因程式中有跑兩個timer以及需要ui form的顯示
所以網路上google了delegate委派這個方法
範例中是使用textbox
我實際測試確實也沒有問題
但若我要換成使用listbox顯示卻是無法顯示
想請教各位先進我有什麼地方弄錯或是遺漏了

像是
ctl.Text = value;
這裡我有嘗試想要寫成
ctl.items.add(value);
但是ctl下並沒有items
所以想請各位先進指點一下

syunmin iT邦新手 5 級 ‧ 2020-09-24 15:51:15 檢舉
感謝各位先進大大的相助
這個問題解決了

但是遇到另一個問題
若是一般非委派的做法我下
ListBox1.SelectedIndex = ListBox1.Items.Count - 1
就可以讓資料都是顯示最新的
但若是目前這種寫法
我卻不清楚該如何讓資料持續顯示最新
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
1
japhenchen
iT邦超人 1 級 ‧ 2020-09-23 13:34:30
最佳解答

你的ctl 沒cast成ListBox

using System;
using System.Windows.Forms;

namespace 兩個時鐘
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            timer1.Interval = 2000;
            timer2.Interval = 2000;
            timer1.Enabled = true;
            timer2.Enabled = true;
        }
        private void timer2_Tick(object sender, EventArgs e)
        {
            UpdateUI(DateTime.Now.ToString("Timer2=>hh:mm:ss"), listBox1);
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            UpdateUI(DateTime.Now.ToString("Timer1=>hh:mm:ss"), listBox1);
        }
        private void UpdateUI(string value, Control ctl)
        {
            if (((ListBox)ctl).InvokeRequired)
            {
                ((ListBox)ctl).Invoke(new MethodInvoker(delegate
                {
                    ((ListBox)ctl).Items.Add(value);
                }));
            }
            else
            {
                ((ListBox)ctl).Items.Add(value);
            }
        }
    }
}

看更多先前的回應...收起先前的回應...
syunmin iT邦新手 5 級 ‧ 2020-09-25 11:41:45 檢舉

感謝大大的相助
這個問題解決了

但是遇到另一個問題
若是一般非委派的做法我下
ListBox1.SelectedIndex = ListBox1.Items.Count - 1
就可以讓資料都是顯示最新的
但若是目前這種寫法
我卻不清楚該如何讓資料持續顯示最新

是指你要讓最後一行被標示並顯示在畫面上嗎?

items.add下面加一行

((ListBox)ctl).SetSelected(((ListBox)ctl).Items.Count - 1, true);
            }
syunmin iT邦新手 5 級 ‧ 2020-09-25 11:55:13 檢舉
private void UpdateUI(string value, Control ctl)
        {
            if (this.InvokeRequired)
            {
                UpdateUICallBack uu = new UpdateUICallBack(UpdateUI);
                this.Invoke(uu, value, (ListBox)ctl);
            }
            else
            {
                ((ListBox)ctl).Items.Add(value);
            }
            ((ListBox)ctl).SetSelected(((ListBox)ctl).Items.Count - 1, true);
        }

大大 我現在是寫成這樣
但是他還是會報跨執行續錯誤,如下
System.InvalidOperationException: '跨執行緒作業無效: 存取控制項 'listBox' 時所使用的執行緒與建立控制項的執行緒不同。'
我這樣寫不對嗎

syunmin iT邦新手 5 級 ‧ 2020-09-26 17:18:41 檢舉

OK 感謝大大 問題解決了

1
小魚
iT邦大師 1 級 ‧ 2020-09-23 00:19:15

Control沒有items這個屬性,
你必須要指定ListBox才可以,
如果硬要寫在同一個Function的話,
可以嘗試這樣

else
{
    if(ctl is ListBox)
        ((ListBox)ctl).items.add(value);
    else
        ctl.Text = value;
}
1
dakala
iT邦新手 5 級 ‧ 2020-09-23 11:12:01

將 UpdateUI 換成下列的 AddToList

private void AddToList(object value)
{
    if (listBox1.InvokeRequired)
    {
        var callback = new Action<object>(AddToList);
        callback.BeginInvoke(value, ar => callback.EndInvoke(ar), callback);
        return;
    }
    listBox1.Items.Add(value.ToString());
}

我要發表回答

立即登入回答