net: [[C#]]

1、单选按钮控件(RadioButton控件)练习

  1. 在设计视图中,拖入一个Button和四个RadioButton,将它们排列在窗口中央。为每个RadioButton设置一个具有区分度的文本。窗口应长这样:

  2. 双击Button,添加一个点击事件处理程序:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    private void button1_Click(object sender, EventArgs e)  
    {
    // 判断哪个RadioButton被选中
    string city = "";
    if (radioButton1.Checked) city = radioButton1.Text;
    else if (radioButton2.Checked) city = radioButton2.Text;
    else if (radioButton3.Checked) city = radioButton3.Text;
    else if (radioButton4.Checked) city = radioButton4.Text;

    // 显示选中的城市
    MessageBox.Show("您选择了:" + city);
    }
  3. 双击Cancel按钮,使得点击该按钮为关闭窗口:

    1
    2
    3
    4
    5
    private void button2_Click(object sender, EventArgs e)  
    {
    // 关闭窗口
    this.Close();
    }
  4. 运行程序,进行测试。

2、列表控件(ListBox控件)练习

  1. 打开Visual Studio,选择“Windows Forms应用程序”模板并创建新项目。

  2. 在设计器中拖入一个ListBox控件,将其放置在窗口中央,并设置一些基本属性,例如Name为listBox1,Width和Height为200,SelectionMode为MultiSimple,实际上SelectionMode属性的值可以根据实际需求进行更改。

  3. 添加一个“添加”按钮和一个“删除”按钮,并编写它们对应的事件处理程序:

    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
    private void btnAdd_Click(object sender, EventArgs e)  
    {
    string itemText = textBox1.Text.Trim();
    if (string.IsNullOrEmpty(itemText))
    {
    MessageBox.Show("请先输入要添加的项目");
    return;
    }

    // 调用Add方法添加新项目
    listBox1.Items.Add(itemText);

    // 清空文本框
    textBox1.Clear();
    }

    private void btnRemove_Click(object sender, EventArgs e)
    {
    if (listBox1.SelectedIndex == -1)
    {
    MessageBox.Show("请先选择要删除的项目");
    return;
    }

    // 调用Remove方法移除选中的项目
    listBox1.Items.RemoveAt(listBox1.SelectedIndex);
    }

在Add按钮单击事件中,我们首先检查文本框中是否有文本,可以通过Trim方法来去除字符串前后的空格,这里我使用了string.IsNullOrEmpty方法进行判断。如果文本框中没有输入,将弹出一个消息框进行提醒,否则将调用AddItem方法添加新项目。

在Remove按钮单击事件中,我们首先检查ListBox是否有任何项被选中,如果没有,将弹出一个消息框进行提醒,否则将使用RemoveAt方法移除选中的项目。

  1. 运行程序,测试看看是否可以正常工作。

3、进度条控件(ProgressBar控件)练习

  1. 打开Visual Studio,创建一个Windows Forms应用程序项目。

  2. 在窗体设计器中加入一个ProgressBar控件和一个Button控件,将按钮的Text属性设置为“开始”。

  3. 设置ProgressBar的Minimum属性为0,Maximum属性为100,Step属性为10。

  4. 在“开始”按钮的Click事件中编写代码,使进度条不断移动,直到达到最大值为止。

    1
    2
    3
    4
    5
    6
    7
    8
    private void button1_Click(object sender, EventArgs e)  
    {
    while (progressBar1.Value < progressBar1.Maximum)
    {
    progressBar1.PerformStep();
    System.Threading.Thread.Sleep(100);
    }
    }

在代码中,使用了while循环和System.Threading.Thread.Sleep方法。while循环的条件是进度条的值小于最大值,每循环一次,进度条的值会增加Step的值。在调用了进度条的PerformStep方法后,使用Thread.Sleep方法让线程休眠一段时间,以便观察进度条的变化,这里的休眠时间设置为100毫秒。

  1. 运行程序,单击“开始”按钮,观察进度条的变化。
  2. 继续使用label将进度显示在窗口上,就出现了问题,这里只有在进度到达100%才会显示。
    1
    2
    3
    4
    5
    6
    7
    8
    private void button1_Click(object sender, EventArgs e)
    {
    while(progressBar1.Value >= 0 && progressBar1.Value < 100) {
    progressBar1.PerformStep();
    System.Threading.Thread.Sleep(1000);
    label1.Text = "当前进度为:" + progressBar1.Value.ToString() + "%";
    }
    }

经检查,原因是该代码段位于事件处理程序 button1_Click 中,当该事件被触发时,程序会执行这段代码。在执行期间,while 循环语句中的代码会一直在进行直到 progressBar1 的值达到了 100。

在这个过程中,每一次循环都会执行 label1.Text 的赋值语句。然而,这个赋值语句执行后,虽然 label1 的文本内容已经被更改了,但你并不能立即看到这些更改,因为程序还没有进入下一次循环或者方法结束。

当程序执行完成之后,最后一次更改 label1 的语句已经被执行了,然后程序结束了。所以,当 progressBar1 的值最终到达 100 时,你才能看到 label1 的内容已经被更改了。

  1. 为了让label能够在程序执行期间动态更新,你需要使用多线程来执行 while 循环以及更新 label1 的操作,这样就可以避免程序在等待循环结束前暂停主线程的执行,从而能够让用户实时观察到 label1 的更改。你可以修改代码如下:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    private void button1_Click(object sender, EventArgs e)  
    {
    // 创建新线程
    Thread newThread = new Thread(delegate ()
    {
    while (progressBar1.Value < 100)
    {
    progressBar1.Invoke(new Action(() => progressBar1.PerformStep()));
    label1.Invoke(new Action(() => label1.Text = "当前进度为:" + progressBar1.Value.ToString() + "%"));
    Thread.Sleep(1000);
    }
    });

    // 启动线程
    newThread.Start();
    }

在这个修改后的代码中,当 button1 被点击时,会创建一个新线程,并在新线程中执行 while 循环以及更新 label1 的操作。使用了 Invoke 方法来确保在主线程执行更新 progressBar1label1 的操作,然后通过 Thread.Sleep 方法使新线程暂停 1 秒钟。这样,你就可以在程序执行期间观察到 label1 的更新了。

  1. 还有一种方法是使用 async/await 关键字来异步执行循环及更新操作,代码如下:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    private async void button1_Click(object sender, EventArgs e)  
    {
    while (progressBar1.Value < 100)
    {
    progressBar1.PerformStep();
    label1.Text = "当前进度为:" + progressBar1.Value.ToString() + "%";
    await Task.Delay(1000);
    }
    }
    在修改后的代码中,button1_Click 方法被声明为异步方法,while 循环及更新 progressBar1label1 的操作被包含在异步执行的任务中,通过 await Task.Delay(1000) 方法使任务暂停 1 秒钟。这样,你也能在程序执行期间观察到 label1 的更新了。

请注意,如果使用 async/await 关键字来异步执行循环及更新操作,你还需考虑到是否会在更新 label1 的过程中出现某些异常,如线程安全问题等,需要进行一定的异常处理。

  1. 测试结果

References