基于数据源c#在运行时自动创建表单

时间:2010-01-03 12:10:43

标签: c# .net datagridview

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

祝你好运, 标记

5 个答案:

答案 0 :(得分:3)

你在做什么听起来很像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是否更容易。或者有一些3rd-party versions的工作方式类似。

答案 1 :(得分:2)

好的,所以我想出了什么!

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

谢谢大家!

答案 2 :(得分:1)

我不完全理解你的问题。是否正确创建一个Windows窗体是否正确,该窗体为对象的所有字段/属性提供输入字段(文本框,复选框等),并将其作为DataSource提供给表单?

您可能必须使用反射(请参阅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:
    // ...
}

但是,将属性类型可靠地映射到正确的输入控件可能相当棘手;例如,当您遇到具有某种未知类的属性作为其类型,或者属性是值集合时,您打算做什么?在某些情况下,您可能必须在表单内创建子表单;在其他情况下,列表框可​​能就足够了。

答案 3 :(得分:0)

我最近构建了一个示例项目,该项目使用ASP.NET的动态数据程序集为WPF网格执行此操作,但我确信您可以将该概念调整为WinForms。动态数据提供的元数据比反射或数据库更丰富,但它确实需要实体数据模型或LINQ to 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;
            }
        }
    }
}

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

答案 4 :(得分:-1)

使用控制数据绑定。它将为您完成所有工作。