mcpField
V
vb-winforms

vb-winforms

github.com/bobmatnyc开发78349 次安装15 周前更新
代码仓库

关于 vb-winforms

此技能为使用 VB.NET 开发 Windows Forms 应用的开发者提供实践模式,涵盖 UI 线程、数据绑定、事件处理、验证和对话框。

主要功能

  1. 01UI 线程与后台任务模式
  2. 02BindingSource 数据绑定
  3. 03事件处理模式
  4. 04表单验证
  5. 05自定义对话框模式

适用场景

  1. 01后台任务期间更新表单
  2. 02将客户数据绑定到控件
  3. 03保存前验证表单输入

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/bobmatnyc/claude-mpm-skills --skill vb-winforms

安装后在 Claude Code 中输入/vb-winforms确认已加载。

附带文件metadata.json

详细介绍

Visual Basic Windows 窗体模式

现代 Windows 窗体开发,使用 VB.NET 并专注于正确的 UI 线程处理、数据绑定和事件处理。

快速入门

' Form definition
Public Class CustomerForm
    Inherits Form

    Private customerService As ICustomerService
    Private bindingSource As New BindingSource()

    Public Sub New()
        InitializeComponent()
        customerService = New CustomerService()
    End Sub

    ' Async load
    Private Async Sub CustomerForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Await LoadCustomersAsync()
    End Sub

    Private Async Function LoadCustomersAsync() As Task
        Try
            Cursor = Cursors.WaitCursor
            Dim customers = Await customerService.GetAllAsync()
            bindingSource.DataSource = customers
            dataGridView.DataSource = bindingSource
        Catch ex As Exception
            MessageBox.Show($"Error loading customers: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        Finally
            Cursor = Cursors.Default
        End Try
    End Function
End Class

UI 线程处理模式

Invoke 与 BeginInvoke
' Update UI from background thread
Private Sub BackgroundWorker_ProgressChanged(sender As Object, e As ProgressChangedEventArgs)
    ' Already on UI thread with BackgroundWorker
    progressBar.Value = e.ProgressPercentage
    lblStatus.Text = $"Processing: {e.ProgressPercentage}%"
End Sub

' Manual invoke when needed
Private Sub UpdateUIFromThread(text As String)
    If lblStatus.InvokeRequired Then
        lblStatus.Invoke(Sub() lblStatus.Text = text)
    Else
        lblStatus.Text = text
    End If
End Sub

' Async pattern
Private Async Sub btnProcess_Click(sender As Object, e As EventArgs) Handles btnProcess.Click
    btnProcess.Enabled = False
    Try
        Dim result = Await Task.Run(Function() LongRunningOperation())
        lblResult.Text = result  ' Safe - back on UI thread
    Finally
        btnProcess.Enabled = True
    End Try
End Sub
BackgroundWorker 模式
Private WithEvents bgWorker As New BackgroundWorker With {
    .WorkerReportsProgress = True,
    .WorkerSupportsCancellation = True
}

Private Sub btnStart_Click(sender As Object, e As EventArgs) Handles btnStart.Click
    If Not bgWorker.IsBusy Then
        bgWorker.RunWorkerAsync()
    End If
End Sub

Private Sub bgWorker_DoWork(sender As Object, e As DoWorkEventArgs) Handles bgWorker.DoWork
    For i = 0 To 100
        If bgWorker.CancellationPending Then
            e.Cancel = True
            Exit For
        End If

        ' Simulate work
        Threading.Thread.Sleep(50)
        bgWorker.ReportProgress(i)
    Next
End Sub

Private Sub bgWorker_ProgressChanged(sender As Object, e As ProgressChangedEventArgs) Handles bgWorker.ProgressChanged
    progressBar.Value = e.ProgressPercentage
End Sub

Private Sub bgWorker_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles bgWorker.RunWorkerCompleted
    If e.Cancelled Then
        MessageBox.Show("Operation cancelled")
    ElseIf e.Error IsNot Nothing Then
        MessageBox.Show($"Error: {e.Error.Message}")
    Else
        MessageBox.Show("Operation completed")
    End If
End Sub

数据绑定

BindingSource 模式
Public Class CustomerForm
    Private bindingSource As New BindingSource()
    Private customers As List(Of Customer)

    Private Async Sub Form_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        customers = Await customerService.GetAllAsync()

        ' Setup binding source
        bindingSource.DataSource = customers

        ' Bind controls
        dataGridView.DataSource = bindingSource
        txtName.DataBindings.Add("Text", bindingSource, "Name")
        txtEmail.DataBindings.Add("Text", bindingSource, "Email")

        ' Navigation
        bindingNavigator.BindingSource = bindingSource
    End Sub

    ' Filter
    Private Sub txtSearch_TextChanged(sender As Object, e As EventArgs) Handles txtSearch.TextChanged
        If String.IsNullOrEmpty(txtSearch.Text) Then
            bindingSource.RemoveFilter()
        Else
            bindingSource.Filter = $"Name LIKE '%{txtSearch.Text}%'"
        End If
    End Sub
End Class
对象数据绑定
' Customer class with INotifyPropertyChanged
Public Class Customer
    Implements INotifyPropertyChanged

    Private _name As String
    Public Property Name As String
        Get
            Return _name
        End Get
        Set(value As String)
            If _name <> value Then
                _name = value
                OnPropertyChanged(NameOf(Name))
            End If
        End Set
    End Property

    Public Event PropertyChanged As PropertyChangedEventHandler _
        Implements INotifyPropertyChanged.PropertyChanged

    Protected Sub OnPropertyChanged(propertyName As String)
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
    End Sub
End Class

事件处理

标准事件模式
' Button click
Private Sub btnSave_Click(sender As Object, e As EventArgs) Handles btnSave.Click
    If ValidateForm() Then
        SaveCustomer()
    End If
End Sub

' Multiple controls, same handler
Private Sub TextBox_TextChanged(sender As Object, e As EventArgs) _
    Handles txtName.TextChanged, txtEmail.TextChanged

    ValidateForm()
End Sub

' Custom event arguments
Public Class CustomerEventArgs
    Inherits EventArgs

    Public Property Customer As Customer

    Public Sub New(customer As Customer)
        Me.Customer = customer
    End Sub
End Class

Public Event CustomerSaved As EventHandler(Of CustomerEventArgs)

Protected Sub OnCustomerSaved(customer As Customer)
    RaiseEvent CustomerSaved(Me, New CustomerEventArgs(customer))
End Sub

窗体验证

Private Function ValidateForm() As Boolean
    errorProvider.Clear()
    Dim isValid = True

    ' Validate name
    If String.IsNullOrWhiteSpace(txtName.Text) Then
        errorProvider.SetError(txtName, "Name is required")
        isValid = False
    End If

    ' Validate email
    If String.IsNullOrWhiteSpace(txtEmail.Text) OrElse Not txtEmail.Text.Contains("@") Then
        errorProvider.SetError(txtEmail, "Valid email is required")
        isValid = False
    End If

    ' Enable/disable save button
    btnSave.Enabled = isValid

    Return isValid
End Function

' Real-time validation
Private Sub txtEmail_Validating(sender As Object, e As System.ComponentModel.CancelEventArgs) _
    Handles txtEmail.Validating

    If Not txtEmail.Text.Contains("@") Then
        errorProvider.SetError(txtEmail, "Invalid email format")
        e.Cancel = True
    Else
        errorProvider.SetError(txtEmail, "")
    End If
End Sub

对话框模式

自定义对话框结果
Public Class CustomerDialog
    Inherits Form

    Public Property Customer As Customer

    Private Sub btnOK_Click(sender As Object, e As EventArgs) Handles btnOK.Click
        If ValidateForm() Then
            Customer = New Customer With {
                .Name = txtName.Text,
                .Email = txtEmail.Text
            }
            DialogResult = DialogResult.OK
            Close()
        End If
    End Sub

    Private Sub btnCancel_Click(sender As Object, e As EventArgs) Handles btnCancel.Click
        DialogResult = DialogResult.Cancel
        Close()
    End Sub
End Class

' Usage
Private Sub ShowCustomerDialog()
    Using dialog = New CustomerDialog()
        If dialog.ShowDialog() = DialogResult.OK Then
            ' Use dialog.Customer
            customers.Add(dialog.Customer)
            RefreshGrid()
        End If
    End Using
End Sub

最佳实践

✅ 应该做
' Use async for I/O operations
Private Async Sub btnLoad_Click(sender As Object, e As EventArgs) Handles btnLoad.Click
    Dim data = Await LoadDataAsync()
End Sub

' Dispose resources properly
Private Sub Form_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
    connection?.Dispose()
    timer?.Dispose()
End Sub

' Use BindingSource for data binding
bindingSource.DataSource = customers
dataGridView.DataSource = bindingSource

' Validate on events
Private Sub txtName_Validating(sender As Object, e As CancelEventArgs) Handles txtName.Validating

' Use ErrorProvider for validation feedback
errorProvider.SetError(txtName, "Name is required")
❌ 不要做
' Don't block UI thread
Private Sub btnLoad_Click(sender As Object, e As EventArgs) Handles btnLoad.Click
    Dim data = LoadDataAsync().Result  ' Blocks UI!
End Sub

' Don't update UI from background thread directly
Task.Run(Sub()
    lblStatus.Text = "Done"  ' WRONG - cross-thread operation
End Sub)

' Don't forget to dispose forms
Dim form = New CustomerForm()
form.Show()  ' Memory leak - use Using or handle FormClosed

' Don't use Application.DoEvents
While processing
    Application.DoEvents()  ' Bad practice - use async instead
End While

相关技能

  • vb-core:VB.NET 核心模式和类型安全
  • vb-database:与 Windows 窗体集成数据库
  • test-driven-development:测试 Windows 窗体应用程序

评论

支持 Markdown