我对数据绑定很新,我需要一些关于如何构建我的应用程序的一般指示。
我有类似数据库的类,如下所示:
public class Database
{
public string FileName { get; set; }
public List<Entry> Entries { get { return backList.ToList(); } }
BindingList<Entry> backList = new BindingList<Entry>();
...
}
其中每个条目的定义如下:
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>();
...
}
我定义了这样的对象模型,因为我知道每个条目肯定包含一个FileName和一个Path。但是&#34;字段的数量和类型&#34;每个条目可能有所不同(字段在别处被定义为抽象)。假设某些条目具有字段&#34; color&#34;,而其他条目不具有。
我想在dataGridView中显示我的条目,我希望它为此目的使用dataBinding。假设我事先知道需要显示哪些列(确保FileName和Path,还有字段&#34; color&#34;和&#34; size&#34;)。
像(伪代码):
dataGridView.Columns[0] --> Entry.FileName
dataGridView.Columns[1] --> Entry.Path
dataGridView.Columns[2] --> Entry.Fields["color"]
dataGridView.Columns[3] --> Entry.Fields["size"]
但是根据我的理解,只能将dataGridView绑定到Entry,这导致:
dataGridView.Columns[0] --> Entry.FileName
dataGridView.Columns[1] --> Entry.Path
dataGridView.Columns[2] --> Entry.Fields {collection}
有什么想法吗?
编辑:
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
}
}
答案 0 :(得分:0)
您可以使用ExpandoObject
创建一个具有在运行时确定的属性的可绑定对象。您需要为每个条目创建一个。
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;
});