2009-05-26 4 views
1

Mon application contient plusieurs formulaires qui consistent en un datagridview fortement typé, une source de liaison fortement typée et un adaptateur de table fortement typé. J'utilise du code dans chaque formulaire pour mettre à jour la base de données chaque fois que l'utilisateur quitte la ligne en cours, déplace le focus loin de la grille de données ou du formulaire, ou ferme le formulaire.Comment lier des événements à des ensembles de données fortement typés de types différents?

Ce code est le même dans chaque cas, donc je veux faire une sous-classe de forme, à partir de laquelle toutes ces formes peuvent hériter.

Mais les objets de données fortement typés héritent tous du composant, ce qui n'expose pas les événements auxquels je veux me lier ou les méthodes que je veux appeler.

La seule façon que je peux voir d'avoir accès aux événements est d'utiliser: Type(string Name).GetEvent(string EventName).AddEventHandler(object Target,Delegate Handler)

De même, je veux appeler la méthode de mise à jour de l'adaptateur de table fortement typé, et je utilise Type(string Name).GetMethod(String name, Type[] params).Invoke(object target, object[] params).

Cela fonctionne bien, mais il semble très lourd. Y a-t-il un meilleur moyen?

Voici mon code pour la classe principale:

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(); 
     } 


    } 
} 

Et est ici une forme (partielle) qui met en œuvre:

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; 

    } 

} 

Répondre

0

Ce demontrastes comment vous pouvez utiliser une base "MustInherit" classe pour vos ensembles de données typés dans le but d'accéder aux propriétés non exposées.

Définissez ceci comme "BaseClass" pour chacun de vos TableAdapters, en remplaçant "System.ComponentModel.Component". En utilisant "MustInherit/MustOverride" ("Abstract" en C#), vous pouvez accéder aux propriétés que vous ne pouvez pas atteindre autrement.

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 

Pour chacun de vos adaptateurs de table que vous définissez pour hériter votre BaseClass vous devez remplacer la propriété requise « MustOverride ». Sans cela, il ne compilera pas. Si vous ajoutez le code mais ne définissez pas la classe de base TableAdapter, il ne compilera pas non plus. C'est une bonne chose; Cela vous assure de bien faire les choses.

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 

Maintenant, vous pouvez mettre toutes sortes de code spécial dans votre SuperTableAdapter. Si vous avez besoin d'accéder à quelque chose qui n'a pas été exposé, utilisez simplement "MustOverride" pour garantir qu'il est disponible.

Questions connexes