WinForms:如何在表单加载后执行代码?

时间:2017-06-03 00:00:03

标签: vb.net forms winforms validation data-binding

我有一个表单用于通过绑定的BrightIdeasSoftware DataListView(围绕.Net ListView控件的包装)更新SQLExpress数据表中的供应商信息。我希望它有两种方式:使用标准的,非参数化的实例化,或者将供应商代码作为参数传递。

使用标准方法一切都很好:来自源和处理的数据加载正常进行。当我尝试在表单的初始化(通过BindingSource.AddNew())中以编程方式将新项添加到绑定源时,我的问题就出现了,因为我在数据源中有不可为空的列。

请注意,AddNew()方法不是罪魁祸首,因为一旦表单处于活动状态它就可以正常工作(后续处理在我计划的EndUpdate()发生之前检查非可空列的值)。但是在表单的OnLoad方法完成后会执行一些自动验证,强制绑定源上的EndUpdate(),并且在验证之后我找不到调用AddNew()的方法。

以下是适用的代码:

    Public Class VendorMaint

      Public Sub New()
        InitializeComponent()
      End Sub

      Public Sub New(code As String, Optional bindingNavigatorVisible As Boolean = False,
       Optional selectionPanelVisible As Boolean = False)
        Me.New()
        Me.BindingNavigatorVisible = bindingNavigatorVisible
        Me.SelectionPanelVisible = selectionPanelVisible
        _HoldInitialVendorCode = code.ToUpper
      End Sub
      Private _HoldInitialVendorCode As String = Nothing

      Public Property BindingNavigatorVisible As Boolean
        Get...
        Set...
      End Property

      Public Property SelectionPanelVisible As Boolean
        Get...
        Set...
      End Property

      Protected Overrides Sub OnLoad(e As System.EventArgs)
        MyBase.OnLoad(e)
        Me.VendorTableAdapter.Fill(Me.InventoryDataSet.Vendor)
      End Sub

      Private Sub DoThisAfterValidation()
        If _HoldInitialVendorCode Is Nothing Then
          Me.DataListView1.SelectedIndex = 0
        Else
          Try
            With Me.DataListView1
              .SelectedItem = (From item In .Items.OfType(Of BrightIdeasSoftware.OLVListItem)() _
               Where (item.SubItems(Me.VendorCodeColumn.Index).Text = _HoldInitialVendorCode) Select item).ToList(0)
            End With
          Catch ex As Exception
            'MsgBox(ex.Message)
            Me.VendorBindingSource.AddNew()
            Me.CodeTextBox.Text = _HoldInitialVendorCode
          End Try
        End If
      End Sub

      Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
        Me.VendorBindingSource.AddNew()
      End Sub

    End Class

DoThisAfterValidation()检查代码是否传递给表单;如果没有,它将DataListView的SelectedIndex设置为0并通过。如果给出了值,则该方法检查代码是否已存在并在那里设置所选项(通过LINQ)。到目前为止,这么好......

但是如果代码被传递但不存在,则抛出并捕获异常,并执行AddNew()方法。如果表单处于活动状态,那么这一切都很好(我使用active来表示在使用中,而不是作为对其Activated事件的引用)。例如,如果我单击Button1,则会创建一个新项目,并且我的字段将按预期显示为空。所以我已经确定表单的初始化导致了我的问题(如下面的堆栈跟踪所示):

NoNullAllowedException was unhandled: Column 'Name' does not allow nulls.

   at System.Data.DataColumn.CheckNullable(DataRow row)
   at System.Data.DataTable.RaiseRowChanging(DataRowChangeEventArgs args, DataRow eRow, DataRowAction eAction, Boolean fireEvent)
   at System.Data.DataTable.SetNewRecordWorker(DataRow row, Int32 proposedRecord, DataRowAction action, Boolean isInMerge, Boolean suppressEnsurePropertyChanged, Int32 position, Boolean fireEvent, Exception& deferredException)
   at System.Data.DataTable.InsertRow(DataRow row, Int64 proposedID, Int32 pos, Boolean fireEvent)
   at System.Data.DataView.FinishAddNew(Boolean success)
   at System.Windows.Forms.CurrencyManager.EndCurrentEdit()
   at System.Windows.Forms.CurrencyManager.ChangeRecordState(Int32 newPosition, Boolean validating, Boolean endCurrentEdit, Boolean firePositionChange, Boolean pullData)
   at System.Windows.Forms.CurrencyManager.set_Position(Int32 value)
   at BrightIdeasSoftware.DataSourceAdapter.HandleListViewSelectionChanged(Object sender, EventArgs e)
   at BrightIdeasSoftware.ObjectListView.OnSelectionChanged(EventArgs e)
   at BrightIdeasSoftware.ObjectListView.HandleApplicationIdle(Object sender, EventArgs e)
   at System.EventHandler.Invoke(Object sender, EventArgs e)
   at System.Windows.Forms.Application.ThreadContext.System.Windows.Forms.UnsafeNativeMethods.IMsoComponent.FDoIdle(Int32 grfidlef)
   at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
   at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
   at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
   at System.Windows.Forms.Application.Run(ApplicationContext context)
   at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
   at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
   at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)
   at InventoryManager.My.MyApplication.Main(String[] Args) in 17d14f5c-a337-4978-8281-53493378c1071.vb:line 81
   at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
   at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
   at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()

我在网上搜索并找到了一些建议,例如在OnLoad()之后的OnShown()方法中执行我的操作,但这并没有让我超越验证点。我尝试通过BeginInvoke和委托使用异步调用,但这不起作用(是的,因为你可以看到我正在显示一个可能干扰消息排队的MsgBox,但我评论说,但仍然没有快乐)。

另外:虽然DataListView(又名ObjectListView)是开源的,但我没有适当的VS.Net组件来编辑/编译CSharp代码,因此我无法在内部更改控件的处理(我希望我能!)。而且我知道我可以将所有必需的值作为参数传递,但这种方式违背了我在这里尝试做的目的(这是让用户输入这些数据)。

有什么想法吗?我提前感谢您的帮助!

P.S。 - 虽然这是偏离主题的,但我意识到使用Try ... Catch块可能不是查找代码是否已定义的最佳实践;如果有人有一个有效的替代方案,我想学习它。谢谢!

0 个答案:

没有答案