这种方法是数据网格视图数据绑定的最佳方法吗?
我见过许多人在绑定datagridviews时遇到问题,经过大量的工作后我发现这是最好的方法。我希望它可以帮助其他人,有人可以增加改进。
步骤1)使用编辑器创建dataGridView及其列。
步骤2)创建一个表示datagridview中一行的对象。
此对象可能包含您需要的任意数量的数据库实例。这是一个包含两个对象(datagridview中的两列)的示例
public class ObjectToShow
{
MyDatabaseObject myDatabaseObject = new MyDatabaseObject();
public ObjectToShow(MyDatabaseObject myDatabaseObject)
{
this.myDatabaseObject = myDatabaseObject;
}
public string Data1 //to asign to a datagridview column
{
get { return myDatabaseObject.data1; }
set { myDatabaseObject.data1 = value; NotifyPropertyChanged("Data1")}
}
public string Data2 //to asign to another datagridview column
{
get { return myDatabaseObject.data2; }
set { myDatabaseObject.data2 = value; NotifyPropertyChanged("Data2"); }
}
//This is to notify the changes made to the object directly and not from the control. This refreshes the datagridview.
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
步骤3)在表格中创建一个ObjectToshow的BindingList和一个bindingSource,如下所示
BindingList<ObjectToshow> ObjectToShow_list = new BindingList<ObjectToshow>();
BindingSource bindingSource = new BindingSource();
步骤4)以这种方式创建绑定
//if we don't put this, each public property in ObjectToshow will generate a new column in the datagridview
//I think it's best to create the columns from the editor.
dataGridView1.AutoGenerateColumns = false;
//database -> <- bindingList -> <- bindingSource -> <- datagridview <- user
bindingSource.DataSource = ObjectToShow_list;
dataGridView1.DataSource = bindingSource;
dataGridView1.Columns["Column_Data1"].DataPropertyName = "Data1";
dataGridView1.Columns["Column_Data2"].DataPropertyName = "Data2";
步骤5)查询数据库
//Example bringing all the data from a database table. This should be done in a controller class.
My_DBModel DB_context = new My_DBModel();
List<myDatabaseObject> myDatabaseObject_list = DB_context.myDatabaseObject.ToList();
//Clear de previous data
ObjectToShow_list.Clear();
//Add the queried elements to the bindingList
foreach (myDatabaseObject item in myDatabaseObject_list)
{
ObjectToshow objectToshow = new ObjectToshow(item);
ObjectToShow_list.Add(objectToshow);
}
步骤6)根据需要修改bindingList或datagridview中的数据。然后是DB_context.saveChanges()。
要添加数据,请将其直接添加到DB_context.myDatabaseObject.Add(new ...)并再次查询数据库;如果你想从datagridview添加它,我认为你必须处理事件并将其添加到上下文中。
这就是我的工作,但它确实有效,但我不确定这是不是最好的方法。提前谢谢。
答案 0 :(得分:2)
所以,为了更好地解释我的想法,我会写一个答案(因为它不会限制我的字符数)但我
我想清楚地表明,我只是添加了关于如何使初始代码变得更好而不是如何变得更好的想法
完成。
说完后让我们进入主题。我将从Step 2) Create an object that represents a row in the datagridview.
开始
因为我认为这就是它的全部意义所在。您的数据库模型(每个表的表和列)有时会反映出来
您的业务模型,但有时在您的业务逻辑中,您需要使用来自2个或更多数据库表的信息
最常见的方法是您选择的方法 - 创建一个代表业务逻辑需求的新类。即便在这里
给出了一些选项,比如使用匿名对象或[NotMapped]
属性,但我会把这些留给实际喜欢的人
任何这些其他选项,因为我也会去一个新的课程。
我将跳过第3步和第4步,因为我认为我没有什么价值可以写出来并直接进入Step 5) query the database
。
我认为应该重新考虑的第一件事是你对每个Model
,View
和Controller
的责任。正如我写的那样
在我的一条评论中,我认为另一个致力于处理数据访问的项目是我发现的最佳方法。为什么我
喜欢这种方法?好吧 - 首先,正如我所写,您的数据库模型很可能不会反映您的业务模型。让你在你的项目中说
有Model
文件夹,你把所有实体和业务对象放在那里。令人困惑的是,即使你会发现一个相当小的应用程序
你自己有很多类,甚至在某些时候你也很难告诉哪个类代表数据库表(实体)和你
用于您的业务逻辑。几个月之后,在你找到那些东西,甚至是你之后,这个男人会更加困难。所以这很简单
可以使你的代码更具可读性的东西,这本身并不是一个小成就。之后再阅读一些关于如何解耦应用程序的内容
如果我们确定一个单独的数据访问项目确实是一个好方法,那么将逻辑放在这个项目中是非常有意义的。
我喜欢这样做的方式(请记住,我没有太多经验,我正在学习,因为我正在写这些东西)是使用Repository
模式。你可以阅读很多
关于这种模式及其使用的不同方式,只是为了向您展示使用存储库而不是
My_DBModel DB_context = new My_DBModel();
List<myDatabaseObject> myDatabaseObject_list = DB_context.myDatabaseObject.ToList();
假设您有两个实体 - User
和Order
。你有一个GenericRepository
来实现你在操作数据时使用的基本方法:
public class GenericRepository<TEntity> : IRepository<TEntity> where TEntity : class
{
internal MyDbContext context;
internal DbSet<TEntity> dbSet;
public GenericRepository(MyDbContext context)
{
this.context = context;
this.dbSet = context.Set<TEntity>();
}
public virtual IQueryable<TEntity> GetAll()
{
return dbSet;
}
public virtual IQueryable<TEntity> GetBy(Expression<Func<TEntity, bool>> predicate)
{
return dbSet.Where(predicate);
}
public virtual TEntity GetById(long id)
{
return dbSet.Find(id);
}
//And so on...
你还有UserRepository
和OrderRepository
这两个都已经从GenericRepository
继承了所有基本方法的每个实体
已实施,因此您不必在每次要执行Delete
或Update
时重复自己。为什么我不喜欢My_DBModel DB_context = new My_DBModel();
?
好吧,假设你使用了一些方法,让我们说GetOrdersBySomething()
,你可以通过查询数据库在代码中的几个地方使用这个方法。如果会发生什么
有人决定编写一个存储过程,从现在开始将返回此信息 - 您必须找到实际使用此方法的所有位置并更改逻辑。
假设几个月后您还必须使用来自Web服务的数据......每次更改都会强制您在应用程序的不同位置重写相同的逻辑。但如果你
使用存储库,您只需GetOrdersBySomething()
OrdersRepository
,并且每当您需要进行更改时,您只能在此处和其他地方进行更改。
另外,如果我正确理解了你的帖子,那么主要的主题是能够从数据库中的几个表中收集数据并将其绑定为数据源。那是什么样的问题 这可能会导致。即使您正在处理相对少量的数据,如果您首先分别查询每个表,然后尝试在服务器端填充您的业务对象 可能会导致严重的性能问题。如果你必须使用3个表,每个表10个列,总共30列。如果您只需要其中的15个,那么您想要的是数据库服务器 做它的工作并以你需要的方式返回那些列,所以服务器端的工作尽可能少。这引出了我指出的下一个主题 - 表达树。我不会 写下很多关于它们的原因我不认为我对它们有一些深刻的理解,但这里是关于http://msdn.microsoft.com/en-us/library/bb882637.aspx主题的官方msdn页面。 可以阅读更多关于表达树是什么,它背后的想法是什么。当你明白表达树究竟是什么时,那么我会更清楚为什么我认为你的例子在哪里 您只查询一个表并不是最好的表,因为当您执行适当的查询时,这种方法确实很有用。
答案 1 :(得分:1)
您可以使用类似
之类的内容将DataGridView
与AutoGenerateColumns绑定到DataSource
dataGridView1.DataSource = [yourDataSource]
然后循环遍历列并在循环中设置它们的属性,这样可以隐藏您不想看到的列,命名标题等。
这就是我的做法
foreach (DataGridViewColumn col in dgvReconciledItems.Columns)
{
switch (col.Name)
{
case "Column1":
col.HeaderText = "Header1";
col.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
col.FillWeight = 30;
break;
case "Column2":
col.HeaderText = "Header2";
col.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
col.FillWeight = 10;
break;
default:
col.Visible = false;
break;
}
}
有任何问题让我知道