Reputation: 525
Data in standart DataGridView looks too empty
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.
Upvotes: 2
Views: 3137
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