Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 基于datasource c在运行时自动创建表单#_C#_.net_Datagridview - Fatal编程技术网

C# 基于datasource c在运行时自动创建表单#

C# 基于datasource c在运行时自动创建表单#,c#,.net,datagridview,C#,.net,Datagridview,我希望在运行时创建一个表单,它将读取任何数据源的列,并根据列和数据类型创建字段,就像datagridviews插入行一样 致以最良好的祝愿, 标记使用控件数据绑定。它将为您完成所有的工作。您正在做的事情听起来很像PropertyGrid已经在工作了,本质上是: foreach(PropertyDescriptor prop in TypeDescriptor.GetProperties(obj)) { object val = prop.GetValue(obj); string

我希望在运行时创建一个表单,它将读取任何数据源的列,并根据列和数据类型创建字段,就像datagridviews插入行一样

致以最良好的祝愿,
标记使用控件数据绑定。它将为您完成所有的工作。

您正在做的事情听起来很像
PropertyGrid
已经在工作了,本质上是:

foreach(PropertyDescriptor prop in TypeDescriptor.GetProperties(obj)) {
    object val = prop.GetValue(obj);
    string s = prop.Converter.ConvertToString(val);
    Control cont = // TODO: create some control and set x/y
    cont.Text = s;
    this.Controls.Add(cont);
}
为避免大量对齐工作,使用
Dock
设置位置可能会有所帮助:

        using(Form form = new Form())
        using (PropertyGrid grid = new PropertyGrid())
        {
            form.Text = obj.ToString(); // why not...
            grid.Dock = DockStyle.Fill;
            form.Controls.Add(grid);
            grid.SelectedObject = obj;
            form.ShowDialog(this);
        }

不过,我想知道在简单的环境中使用
PropertyGrid
是否更容易。或者有一些类似的方法。

我不完全理解你的问题。您是否希望创建一个Windows窗体,为作为其
数据源提供给窗体的对象的所有字段/属性提供输入字段(文本框、复选框等)

您可能必须为此使用反射(请参阅
System.reflection
命名空间)。例如,要获取所有属性的列表,请执行以下操作:

using System.Reflection;

....

public object DataSource;

...

Debug.Assert( DataSource != null );
var properties = DataSource.GetType().GetProperties();
然后,您将为每个属性实例化一个输入控件:

foreach ( var property in properties )
{
    // extract some information about each property:
    string propertyName = property.Name;
    Type propertyType = property.PropertyType;
    bool propertyReadOnly = !property.CanWrite;

    // create input controls based on this information:
    // ...
}

然而,将属性类型可靠地映射到正确的输入控件可能相当棘手;例如,当遇到类型为未知类的属性时,或者当属性是值的集合时,您将怎么做?在某些情况下,您可能需要在表单内部创建子表单;在其他情况下,一个列表框可能就足够了。

我最近构建了一个示例项目,该项目使用ASP.NET的动态数据程序集来为WPF网格执行此操作,但我相信您可以将此概念应用于WinForms。动态数据提供了比反射或数据库更丰富的元数据,但它确实需要实体数据模型或LINQ到SQL数据模型

基本上,您只需参考System.Web.DymamicData,也许您可以在我的课堂上找到一些有用的内容:

public class DynamicDataGridBuilder<TContext, TEntity> where TEntity : EntityObject
{
    readonly MetaModel model = new MetaModel();
    public DynamicDataGridBuilder()
    {            
        model.RegisterContext(typeof(TContext), new ContextConfiguration { ScaffoldAllTables = true });
    }

    public void BuildColumns(DataGrid targetGrid)
    {
        MetaTable metaTable = model.GetTable(typeof(TEntity));

        // Decision whether to auto-generated columns still rests with the caller.
        targetGrid.Columns.Clear();
        foreach (var metaColumn in metaTable.Columns.Where(x => x.GetType().Name == "MetaColumn" && x.Scaffold))      
        {
            switch (metaColumn.ColumnType.Name)
            {
                case "Boolean":
                    targetGrid.Columns.Add(new DataGridCheckBoxColumn { Binding = new Binding(metaColumn.Name), Header = metaColumn.DisplayName });
                    break;
                default:
                    targetGrid.Columns.Add(new DynamicDataGridTextColumn { MetaColumn = metaColumn, Binding = new Binding(metaColumn.Name), Header = metaColumn.DisplayName });
                    break;
            }
        }
    }
}
公共类DynamicDataGridBuilder,其中tenty:EntityObject
{
只读元模型模型=新元模型();
公共动态网格生成器()
{            
RegisterContext(typeof(TContext),新ContextConfiguration{ScaffoldAllTables=true});
}
公共void BuildColumns(DataGrid targetGrid)
{
MetaTable MetaTable=model.GetTable(typeof(tenty));
//是否自动生成列仍取决于调用方。
targetGrid.Columns.Clear();
foreach(metaTable.Columns.Where(x=>x.GetType().Name==“metaColumn”&&x.Scaffold)中的var metaColumn)
{
开关(metaColumn.ColumnType.Name)
{
案例“布尔”:
添加(新DataGridCheckBoxColumn{Binding=newbinding(metaColumn.Name),Header=metaColumn.DisplayName});
打破
违约:
targetGrid.Columns.Add(新的DynamicDataGridTextColumn{MetaColumn=MetaColumn,Binding=new Binding(MetaColumn.Name),Header=MetaColumn.DisplayName});
打破
}
}
}
}

TContext是对象模型的类型,TEntity是该模型中要为其生成控件的实体/类的类型。

好的,下面是我的想法

public partial class Form2 : Form
{
    private Boolean isBrowsable(PropertyInfo info)
    {
        return info.GetCustomAttributes(typeof(BrowsableAttribute), false).Length>-1;
    }
    public Form2()
    {
        InitializeComponent();
    }
    public Form2(Boolean showCheckBoxes)
    {
        InitializeComponent();
        _showCheckBoxes = true;
    }

    private Boolean _showCheckBoxes;
    private Object _reflection;
    private TableLayoutPanel _table =  new TableLayoutPanel{Dock=DockStyle.Fill, CellBorderStyle = TableLayoutPanelCellBorderStyle.Single};

    public Object SelectedObject
    {
        get
        {
            return _reflection;
        }
        set
        {
            //clear all controls from the table
            _table.Controls.Clear();

            foreach (var property in _reflection.GetType().GetProperties())
            {
                if (isBrowsable(property))
                {
                    if ((property.PropertyType == typeof(int)) || (property.PropertyType == typeof(string)))
                    {
                        var textField = new TextBox { Dock = DockStyle.Fill, AutoSize = true };
                        textField.DataBindings.Add("Text", _reflection, property.Name);


                        _table.Controls.Add(textField, 2, _table.RowCount += 1);

                        var propertyLabel = new Label
                        {
                            Text = property.Name,
                            Dock = DockStyle.Fill,
                            TextAlign = ContentAlignment.MiddleLeft
                        };

                        _table.Controls.Add(propertyLabel, 1, _table.RowCount);

                        if (_showCheckBoxes)
                        {
                            var checkBox = new CheckBox
                                               {
                                                   AutoSize = true,
                                                   Name = property.Name,
                                                   Dock = DockStyle.Left,
                                                   CheckAlign = ContentAlignment.TopLeft
                                               };
                            _table.Controls.Add(checkBox, 0, _table.RowCount);
                        }
                    }
                }
            }
            //add one extra row to finish alignment

            var panel = new Panel { AutoSize = true };
            _table.Controls.Add(panel, 2, _table.RowCount += 1);
            _table.Controls.Add(panel, 1, _table.RowCount);
            if (_showCheckBoxes)
            {
                _table.Controls.Add(panel, 0, _table.RowCount);
            }
            Controls.Add(_table);


            if (!Controls.Contains(_table))
                Controls.Add(_table);
        }
    }

    public Boolean Execute(Object reflection)
    {
        SelectedObject = reflection;
        return ShowDialog() == DialogResult.OK;
    }
}

谢谢大家

它应该很简单,只需循环列集合并实例化新控件。对于数据绑定,它最好使用
TypeDescriptor
/
PropertyDescriptor
,以支持
ICustomTypeDescriptor
TypeDescriptionProvider
ITypedList
,等等,这就是上述propertygrid在内部的工作方式吗?是的,没错。理想情况下,我想做的是显示一个表单,其中包含一个datagrid,允许用户选择一行并返回数据绑定对象(数据源由外部源指定)。然后,数据源应该可以通过其任何一个属性(使用linq)进行过滤,因此外部源将调用类似Customer selectedCustomer的东西=(Customer)new SearchResult().Execute(DALConnector.Dc.Customers);公共部分类SearchResult:Form{public Object Execute(Object dataSource){SearchResults.dataSource=dataSource;if(ShowDialog()==DialogResult.OK){if(SearchResults.CurrentRow!=null)return SearchResults.CurrentRow.DataBoundItem;}返回null;}不,不会。数据绑定只在有控件要绑定的情况下工作。propertygrid如何获取名称和数据类型。这正是我需要的,只是我想制作一个自定义格式。我想它可以扩展它….?prop.Name、prop.DisplayName、prop.PropertyType等。这太棒了!我发现了一些问题:属性SelectedObject的Setter没有使用它的值param。您只是通过构造函数设置目标对象。而且,您只能有一个构造函数:
public Form2(object reflection=null,Boolean showcheckbox=false)