简体   繁体   English

使用IEnumerable将数据绑定到对象 <T> 属性-C#

[英]DataBinding to an object with an IEnumerable<T> property - C#

I am quite new to databinding and I need some general directions on how to structure my application. 我对数据绑定还很陌生,我需要一些有关如何构造应用程序的一般指导。

I have a database-like class like the following: 我有一个类似于数据库的类,如下所示:

public class Database
{
    public string FileName { get; set; }
    public List<Entry> Entries { get { return backList.ToList(); } }

    BindingList<Entry> backList = new BindingList<Entry>();
    ...
}

where each entry is defined as follows: 其中每个条目的定义如下:

public class Entry
{
    public string FileName { get; set; }
    public string Path { get; set; }
    FileInfo File { get; set; }
    public Dictionary<string, Field> Fields { get { return fields.ToDictionary(n => n.Name, f => f); } }
    HashSet<Field> fields = new HashSet<Field>();
    ...
}

I defined my object model like this because I know that each entry will for sure contain a FileName and a Path. 我之所以这样定义对象模型,是因为我知道每个条目肯定会包含一个FileName和一个Path。 But the number and type of "fields" each entry has it might be different (field is defined elsewhere as abstract). 但是每个条目具有的“字段”的数量和类型可能会有所不同(字段在其他地方定义为抽象的)。 Assume some entries have the field "color", while others don't. 假设某些条目具有“颜色”字段,而其他条目则没有。

I want to display my entries in a dataGridView, and I want it to use dataBinding for this purpose. 我想在dataGridView中显示我的条目,并且我希望它为此使用dataBinding。 Assume I know in advance which columns need to be displayed (for sure FileName and Path, but also the fields "color" and "size"). 假设我事先知道需要显示哪些列(请确保FileName和Path,以及字段“ color”和“ size”)。

Something like (pseudo-code): 类似于(伪代码)的东西:

dataGridView.Columns[0] --> Entry.FileName
dataGridView.Columns[1] --> Entry.Path
dataGridView.Columns[2] --> Entry.Fields["color"]
dataGridView.Columns[3] --> Entry.Fields["size"]

But from my understanding, it is possible only to bind dataGridView to Entry, which results in this: 但是据我了解,仅可能将dataGridView绑定到Entry,这将导致:

dataGridView.Columns[0] --> Entry.FileName
dataGridView.Columns[1] --> Entry.Path
dataGridView.Columns[2] --> Entry.Fields {collection}

Any ideas? 有任何想法吗?


EDIT: 编辑:

Example for Servy: 服务示例:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Dynamic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace DataBindingTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            InitDataGridView();
        }

        void InitDataGridView()
        {
            DataGridView dgv = new DataGridView();
            dgv.AutoGenerateColumns = true;
            dgv.Dock = DockStyle.Fill;
            this.Controls.Add(dgv);

            Database db = new Database();

            string[] colors = new string[5]{"red","orange","yellow","green","blue"};

            for (int i = 0; i < 5; i++)
            {
                db.Add(
                    new Entry(
                        @"C:\Test\file_" + i + ".jpg",
                        new SingleField("color", colors[i]),
                        new DateField("date_created", DateTime.Now.AddDays((int)i))
                            )
                        );
            }

            var query = db.Entries.Select(entry => 
            {
                IDictionary<string, object> mappings = new ExpandoObject();
                dynamic newEntry = mappings;
                newEntry.FileName = entry.FileName;
                newEntry.Path = entry.Path;
                foreach (var field in entry.Fields)
                {
                    mappings[field.Key] = field.Value;
                }
                return newEntry;
            });

            dgv.DataSource = query.ToList();    //  Empty dataGridView
            //dgv.DataSource = db.Entries;      //  Populated dataGridView
        }
    }

    public class Database
    {
        public string FileName { get; set; }

        BindingList<Entry> entries = new BindingList<Entry>();
        public BindingList<Entry> Entries { get { return entries; } }

        public void Add(Entry newEntry)
        {
            //  ToDo: code for checking newEntry
            //
            entries.Add(newEntry);
        }
    }

    public class Entry
    {
        public string FileName { get; set; }
        public string Path { get; set; }
        FileInfo File { get; set; }

        public Dictionary<string, Field> Fields { get { return fields.ToDictionary(n => n.Name, f => f); } }
        HashSet<Field> fields = new HashSet<Field>();

        public Entry(string fileName, params Field[] fieldParams)
        {
            File = new FileInfo(fileName);
            FileName = File.Name;
            Path = File.Directory.FullName;

            foreach (Field f in fieldParams)
            {
                fields.Add(f);
            }
        }
    }

    public abstract class Field
    {
        public string Name { get; protected set; }
        public object Value { get; protected set; }
        public FieldType Type { get; protected set; }

        public Field(string name, object value)
        {
            Name = name;
            Value = value;
        }
    }

    public class SingleField : Field
    {
        public SingleField(string name, string value) : base (name, value)
        {
            Type = FieldType.Single;
        }
    }

    public class MultipleField : Field
    {
        public MultipleField(string name, params string[] values) : base (name, values)
        {
            Type = FieldType.Multiple;
        }
    }

    public class DateField : Field
    {
        public DateField(string name, DateTime date) : base (name, date)
        {
            Type = FieldType.Date;
        }
    }

    public enum FieldType
    {
        Single,
        Multiple,
        Date
    }
}

You can use an ExpandoObject to create a bindable object with properties determined at runtime. 您可以使用ExpandoObject创建具有在运行时确定的属性的可绑定对象。 You'll need to create one for each of your entries. 您需要为每个条目创建一个。

var query = entries.Select(entry => 
{
    IDictionary<string, object> mappings = new ExpandoObject();
    dynamic newEntry = mappings;
    newEntry.FileName = entry.FileName;
    newEntry.Path = entry.Path;
    foreach(var field in fields)
        mappings[field.Key] = field.Value);
    return newEntry;
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM