2009-05-26 4 views
1

Meine Anwendung enthält mehrere Formulare, die aus einem stark typisierten Datagridview, einer stark typisierten Bindungsquelle und einem stark typisierten Tabellenadapter bestehen.Wie kann ich Ereignisse an stark typisierte Datasets verschiedener Typen binden?

Ich verwende in jedem Formular einen Code, um die Datenbank zu aktualisieren, wenn der Benutzer die aktuelle Zeile verlässt, den Fokus vom Datagrid oder vom Formular verschiebt oder das Formular schließt.

Dieser Code ist in jedem Fall gleich, also möchte ich eine Unterklasse der Form machen, von der alle diese Formen erben können.

Aber die stark typisierten Datenobjekte erben alle von der Komponente, die die Ereignisse, an die ich binden will, oder die Methoden, die ich aufrufen möchte, nicht offen legen.

Der einzige Weg, ich, um Zugang zu den Ereignissen sehen kann, ist zu verwenden: Type(string Name).GetEvent(string EventName).AddEventHandler(object Target,Delegate Handler)

Ebenso mag ich die Update-Methode der stark typisierten Tabellenadapter nennen und Type(string Name).GetMethod(String name, Type[] params).Invoke(object target, object[] params) verwenden.

Es funktioniert in Ordnung, aber es scheint sehr schwer zu händeln. Gibt es einen besseren Weg?

Hier ist mein Code für die Hauptklasse:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 
using System.Data; 
using System.Data.SqlClient; 
using System.ComponentModel; 

namespace MyApplication 
{ 
    public class AutoSaveDataGridForm: Form 
    { 
     private DataRow PreviousRow; 

     public Component Adapter 
     { 
      private get; 
      set; 
     } 


     private Component dataGridView; 
     public Component DataGridView 
     { 
      private get 
      { 
       return dataGridView; 
      } 
      set 
      { 
       dataGridView = value; 
       Type t = dataGridView.GetType(); 
       t.GetEvent("Leave").AddEventHandler(dataGridView, new EventHandler(DataGridView_Leave)); 

      } 
     } 
     private Component bindingSource; 
     public Component BindingSource 
     { 
      private get 
      { 
       return bindingSource; 
      } 
      set 
      { 
       bindingSource = value; 
       Type t = bindingSource.GetType(); 
       t.GetEvent("PositionChanged").AddEventHandler(bindingSource, new EventHandler(BindingSource_PositionChanged)); 


      } 
     } 



     protected void Save() 
     { 
      if (PreviousRow != null && PreviousRow.RowState != DataRowState.Unchanged) 
      { 
       Type t = Adapter.GetType(); 
       t.GetMethod("Update", new Type[] { typeof(DataRow[]) }).Invoke(Adapter, new object[] { new DataRow[] { PreviousRow } }); 

      } 

     } 


     private void BindingSource_PositionChanged(object sender, EventArgs e) 
     { 
      BindingSource bindingSource = sender as BindingSource; 
      DataRowView CurrentRowView = bindingSource.Current as DataRowView; 
      DataRow CurrentRow = CurrentRowView.Row; 
      if (PreviousRow != null && PreviousRow != CurrentRow) 
      { 
       Save(); 
      } 
      PreviousRow = CurrentRow; 

     } 

     private void InitializeComponent() 
     { 
      this.SuspendLayout(); 
      // 
      // AutoSaveDataGridForm 
      // 
      this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.AutoSaveDataGridForm_FormClosed); 
      this.Leave += new System.EventHandler(this.AutoSaveDataGridForm_Leave); 
      this.ResumeLayout(false); 

     } 

     private void DataGridView_Leave(object sender, EventArgs e) 
     { 
      Save(); 
     } 

     private void AutoSaveDataGridForm_FormClosed(object sender, FormClosedEventArgs e) 
     { 
      Save(); 
     } 

     private void AutoSaveDataGridForm_Leave(object sender, EventArgs e) 
     { 
      Save(); 
     } 


    } 
} 

Und hier ist eine (teilweise) Form, die es implementiert:

Diese demontrastes
public partial class FileTypesInherited :AutoSaveDataGridForm 
{ 
    public FileTypesInherited() 
    { 
     InitializeComponent(); 
    } 

    private void FileTypesInherited_Load(object sender, EventArgs e) 
    { 
     // TODO: This line of code loads data into the 'sharedFoldersInformationV2DataSet.tblFileTypes' table. You can move, or remove it, as needed. 
     this.tblFileTypesTableAdapter.Fill(this.sharedFoldersInformationV2DataSet.tblFileTypes); 
     this.BindingSource = tblFileTypesBindingSource; 
     this.Adapter = tblFileTypesTableAdapter; 
     this.DataGridView = tblFileTypesDataGridView; 

    } 

} 

Antwort

0

, wie Sie eine "MustInherit" Basis verwenden können Klasse für Ihre typisierten Datasets für den Zugriff auf unbelichtete Eigenschaften.

Legen Sie dies als "BaseClass" für jeden Ihrer typisierten TableAdapter fest und ersetzen Sie "System.ComponentModel.Component". Mit "MustInherit/MustOverride" ("Abstract" in C#) gelangen Sie zu den Eigenschaften, die Sie sonst nicht erreichen können.

Public MustInherit Class SuperTableAdapter 
    Inherits System.ComponentModel.Component 

    Public MustOverride ReadOnly Property MyCommandCollection As Data.SqlClient.SqlCommand() 

    Public Sub New() 
     MyBase.New() 
     'With the command collection exposed, you can replace it with your own. You can do the same for events.' 

     For i = 0 To MyCommandCollection.Length - 1 
      Dim myspecialCommand As New Data.SqlClient.SqlCommand() 
      MyCommandCollection(i) = myspecialCommand 
     Next 
    End Sub 
End Class 

Für jede Ihrer Tischadapter, die Sie setzen Ihre Baseclass erben Sie die erforderliche „Mustoverride“ Eigenschaft außer Kraft setzen müssen. Ohne es wird es nicht kompilieren. Wenn Sie den Code hinzufügen, aber nicht die TableAdapter-Basisklasse festlegen, wird sie auch nicht kompiliert. Das ist eine gute Sache. es stellt sicher, dass Sie es richtig machen.

Namespace DataSet1TableAdapters 
    Partial Public Class Table1TableAdapter 
     Public Overrides ReadOnly Property MyCommandCollection As System.Data.SqlClient.SqlCommand() 
      Get 
       Return Me.CommandCollection 
      End Get 
     End Property 
    End Class 

    Partial Public Class Table2TableAdapter 
     Public Overrides ReadOnly Property MyCommandCollection As System.Data.SqlClient.SqlCommand() 
      Get 
       Return Me.CommandCollection 
      End Get 
     End Property 
    End Class 
End Namespace 

Jetzt können Sie alle Arten von speziellen Code in Ihrem SuperTableAdapter setzen. Wenn Sie auf etwas zugreifen müssen, das nicht verfügbar war, verwenden Sie einfach "MustOverride", um sicherzustellen, dass es verfügbar ist.

Verwandte Themen