首頁 C# WinForom UI 事件更新元件處理
文章
Cancel

C# WinForom UI 事件更新元件處理

前言

使用Winfrom或WPF 製作桌面小程式的時候會用到

問題描述

按下Button時,畫面會卡住,畫面無法達到「按下按鈕 ->按鈕鎖定 ->執行商業邏輯 ->執行完畢 ->按鈕鎖定」這樣的基本效果

解法

使用BackgroundWorker可以解決上述的問題點

Sol:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public partial class MainWindow : Window
{
    private BackgroundWorker worker = new BackgroundWorker();
    public MainWindow()
    {
        InitializeComponent();
        this.worker.DoWork += new DoWorkEventHandler(worker_DoWork);
        this.worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
    }
    private void Button_Click(object sender, RoutedEventArgs e)
    {
        if (this.Button.IsEnabled == true) this.Button.IsEnabled = false;
        worker.RunWorkerAsync();
    }
    void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if (this.Button.IsEnabled == false) this.Button.IsEnabled = true;
    }
    void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        doSomeThing();
    }
    private void doSomeThing()
    {
        Task Task1 = Task.Run(() => {
        /*
         * 商業邏輯放這邊
         */
        });
        Task.WaitAll(Task1);
    }
}

BackgroundWorker執行時更新UI控件的靜態擴展

由於有時候需要將Value傳回給UI的執行續,所以需要

使用方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class main
{
    ComboBox cb = new ComboBox();
 
    void main()
    {
        //方法1:使用lambda
        cb.InvokeIfRequired(() =>
        {
            cb.Text = "hello";
        });
 
        //方法2:使用Action
        cb.InvokeIfRequired(helloAction);
    }
 
    void helloAction()
    {
        cb.Text = "hello";
    }
}

Sol:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static class Extensions
{
    //非同步委派更新UI
    public static void InvokeRequired(this Control control, MethodInvoker action)
    {
        if (control.InvokeRequired)
        {
            control.Invoke(action);
        }
        else
        {
            action();
        }
    }
}

BackgroundWorker執行時更新UI控件的靜態擴展(WPF版本)

使用方式

1
2
3
4
private void UpdateProgress(string message)
{
    ProgressLabel.InvokeIfNeeded(() => ProgressLabel.Content = message);
}

Sol:

1
2
3
4
5
6
7
8
9
10
11
public static void InvokeIfNeeded(this Control control, Action action)
{
    if (control.Dispatcher.CheckAccess())
    {
        action();
    }
    else
    {
        control.Dispatcher.Invoke(action);
    }
}
本文由作者按照 CC BY 4.0 進行授權