DmitryB
DmitryB

Reputation: 525

WinForms. How to find TableAdapter and Fill DataTable at Design-Time

Data in standart DataGridView looks too empty

enter image description here

and it is unclear how data look in customized, filled grid

I'm going to extend grid to look more complex but the result it will be visible only at run-time, when it have data.

So I want to fill DataTable at design time to see how the result looks in the Grid. So I need to perfrom code

this.MyDataTableTableAdapter.Fill(this.dBTestDataSet.MyDataTable)

I can get this.dBTestDataSet.MyDataTable from DataSource when DataSource is assigned by BindingSource using next code:

  if ((DataSource is BindingSource) && String.IsNullOrEmpty(DataMember))
  {
    BindingSource bindingSource = (DataSource as BindingSource);
    if ((bindingSource.DataSource is DataSet) && (bindingSource.DataMember is String))
    {
      DataSet dataSet = (bindingSource.DataSource as DataSet);
      DataTable dataTable = dataSet.Tables[bindingSource.DataMember];
      return dataTable;
    }
  }

now I have MyDataTable

but how can I get MyDataTableTableAdapter?

I don't see any connection between MyDataTable and MyDataTableTableAdapter in the porject code

Although the development environment correctly shows the DataAdapter under every DataTable.

enter image description here

enter image description here

Upvotes: 2

Views: 3137

Answers (1)

Reza Aghaei
Reza Aghaei

Reputation: 125292

I believe it's not a good idea to load actual data to designer. You can fill DataGridView using some fake data, the same way which web forms designer do it for ASP.NET GridView control.

Q: How can I get MyDataTableTableAdapter? I don't see any connection between MyDataTable and MyDataTableTableAdapter in the porject code.

Each dataset has an XSD file which contains the definition of data set schema and also contains some annotations which will be used for generating TableAdapter classes, for example it contains some nodes like:

<TableAdapter BaseClass="System.ComponentModel.Component" 
 DataAccessorModifier="AutoLayout, AnsiClass, Class, Public" 
 DataAccessorName="CategoryTableAdapter" 
 GeneratorDataComponentClassName="CategoryTableAdapter" 
 Name="Category"
 UserDataComponentName="CategoryTableAdapter">

You can parse the file and extract the related TableAdapter for the DataTable. As you can see above xml is the point which TableAdapter and DataTable relates to each other.

You can get the xsd file using Visual Studio API methods. Also as a more simple workaround you can set its BuildAction to Embedded Resource and get it from the compiled assembly.

Note

Another option which may satisfy your requirement is putting your DataGridView control in UserControl and load data in constructor of UserControl, this way when you put an instance of your UserControl on a form, since the designer executes the constructor of your UserControl then the DataGridView will be filled with data.

Then if you want to expose Columns property of DataGridView you can use this solution.

Example - Just for learning purpose

using System;
using System.Linq;
using System.Windows.Forms;
using System.Data;
using System.Reflection;
using System.IO;
using System.Xml.Linq;
public class MyDataGridView : DataGridView
{
    protected override void OnDataSourceChanged(EventArgs e)
    {
        base.OnDataSourceChanged(e);
        TryToPopulateControl();
    }
    protected override void OnDataMemberChanged(EventArgs e)
    {
        base.OnDataMemberChanged(e);
        TryToPopulateControl();
    }
    private void TryToPopulateControl()
    {
        if (!DesignMode)
            return;
        else
        {
            try
            {
                if (this.DataSource is BindingSource)
                {
                    var bs = (BindingSource)this.DataSource;
                    if (bs.DataSource is DataSet)
                    {
                        var ds = bs.DataSource;
                        var table = bs.DataMember;
                        if (ds == null || string.IsNullOrEmpty(table))
                            return;
                        var name = ds.GetType().FullName + ".xsd";
                        string result = "";
                        using (var stream = Assembly.GetExecutingAssembly()
                               .GetManifestResourceStream(name))
                            using (StreamReader reader = new StreamReader(stream))
                            result = reader.ReadToEnd();
                        var document = XDocument.Parse(result);
                        var node = document.Descendants()
                            .Where(x => x.Name.LocalName == "TableAdapter")
                            .Where(x => x.Attribute("Name").Value == table).FirstOrDefault();
                        if (node != null)
                        {
                            var tableAdapterName = node.Attribute("UserDataComponentName").Value;
                            var adapterType = Assembly.GetExecutingAssembly()
                                .GetTypes().Where(x => x.Name == tableAdapterName).FirstOrDefault();
                            var adapter = Activator.CreateInstance(adapterType);
                            var fillMethod = adapterType.GetMethod("GetData");
                            var dataTable = fillMethod.Invoke(adapter, new object[] { }) as DataTable;
                            foreach (DataRow row in dataTable.Rows)
                                ((DataSet)ds).Tables[table].Rows.Add(row.ItemArray);
                        }
                    }
                }
            }
            catch (Exception)
            {
                //Could not load data
            }
        }
    }
}

Upvotes: 1

Related Questions