Как я могу связать события со строго типизированными наборами данных разных типов? - PullRequest
1 голос
/ 26 мая 2009

Мое приложение содержит несколько форм, которые состоят из строго типизированной таблицы данных, строго типизированного источника привязок и адаптера таблицы со строгой типизацией.

Я использую некоторый код в каждой форме для обновления базы данных всякий раз, когда пользователь покидает текущую строку, смещает фокус с сетки данных или формы или закрывает форму.

Этот код одинаков в каждом случае, поэтому я хочу создать подкласс формы, от которого могут наследоваться все эти формы.

Но строго типизированные объекты данных наследуются от компонента, который не отображает события, к которым я хочу привязаться, или методы, которые я хочу вызвать.

Единственный способ получить доступ к событиям - это использовать: Type(string Name).GetEvent(string EventName).AddEventHandler(object Target,Delegate Handler)

Точно так же я хочу вызвать метод Update для строго типизированного адаптера таблицы и использую Type(string Name).GetMethod(String name, Type[] params).Invoke(object target, object[] params).

Это работает нормально, но кажется очень тяжелым. Есть ли лучший способ?

Вот мой код для основного класса:

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


    }
}

А вот (частичная) форма, которая ее реализует:

    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;

    }

}

1 Ответ

0 голосов
/ 15 мая 2010

Это демонстрирует, как вы можете использовать базовый класс "MustInherit" для ваших набранных наборов данных для доступа к неэкспонированным свойствам.

Установите это как «BaseClass» для каждого из ваших типизированных адаптеров таблиц, заменив «System.ComponentModel.Component». Используя «MustInherit / MustOverride» («Абстрактный» в C #), вы можете получить свойства, которые иначе не будут доступны.

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

Для каждого из ваших адаптеров таблиц, которые вы установили для наследования базового класса, вы должны переопределить обязательное свойство "MustOverride". Без этого он не скомпилируется. Если вы добавите код, но не установите базовый класс TableAdapter, он также не будет компилироваться. Это хорошая вещь; это гарантирует, что вы делаете это правильно.

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

Теперь вы можете поместить все виды специального кода в свой SuperTableAdapter. Если вам нужен доступ к тому, что не было открыто, просто используйте «MustOverride», чтобы гарантировать его доступность.

...