当我从BindingList更新datagriview时,偶尔会收到错误“Bindingsource不能成为自己的数据源”。在涉及抛出错误时,我没有任何押韵或理由。如果有人有一些见解,我们非常感激。
dgv_Items.DataSource = null;
dgv_Items.DataSource = new BindingSource(Item.ObjectsItem.OrderBy(x => x.Quality), null);
foreach (DataGridViewRow row in dgv_Items.Rows)
{
try
{
if (row.Cells[5].Value != null)
{
var cell = row.Cells[5].Value;
if (Uri.IsWellFormedUriString(cell.ToString(), UriKind.Absolute))
{
DataGridViewLinkCell linkCell = new DataGridViewLinkCell
{
LinkColor = Color.Blue,
Value = cell
};
row.Cells[5] = linkCell;
}
}
}
catch (Exception ex)
{
Main.Log("Error: " + ex);
}
}
答案 0 :(得分:1)
bindingsource用于将数据绑定到显示的数据。在您的情况下,显示的数据是数据网格视图。
如果您决定使用绑定源作为DataGridView的数据源,则不应再以编程方式处理DataGridView。因为您告诉DataGridView它的DataSource将是您的BindingSource,所以您的程序应该只通过更改DataSource中的数据来更改数据。一旦更改,DataGridview和BindingSource将注意相应的显示项目更新。
同样,如果操作员更改显示的项目,DataGridView和BindingSource将注意相应的对象更新。
一旦设置了DataGridView的DataSource,就不应该以编程方式更改DataGridView,而是更改DataSource中的数据。
您希望显示URI字符串,问题是如果它发生更改,则没有人会收到有关这些更改的通知,因此没有人可以对更改做出反应。原因是因为类字符串没有实现接口INotifyPropertyChanged
所以我们必须创建一个要显示的URI字符串类。
public class MyDisplayableUriString
{
public string UriString {get; set;}
... // if desired other properties
}
我们希望表单显示MyDisplayableUriString列表:
您应该会在DataGridView中看到MyDisplayableUriString的字段。
在此事件处理程序中,使用多个可显示的URi字符串填充BindingSource:
private void Form1_Load(object sender, EventArgs e)
{
for (int i = 0; i < 10; ++i)
{
MyDisplayableUriString uriItem = new MyDisplayableUriString()
{
Uri = "URI " + i.ToString()
};
this.bindingSource1.Add(uriItem);
}
}
如果您运行该程序,您应该看到该表填充了创建的URI项。
现在让我们更改其中一项:
添加按钮并为按钮单击创建处理程序:
private void button1_Click(object sender,EventArgs e) { MyDisplayableUriString uriItem =(MyDisplayableUriString)this.bindingSource1 [0]; uriItem.UriString =“John”; }
现在,如果您运行该程序并单击该按钮,则名称不会更新。
原因是您的类没有实现INotifyPropertyChanged。因此,当更改uri项目时,不会通知bindingsource。因此DataGridView不会更新。
幸运的是,StackOverflow有一篇关于正确实现的文章: Implementing INotifyPropertyChanged
代码如下:
public event PropertyChangedEventHandler PropertyChanged;
private string uriName = null;
public string UriName
{
get { return this.uriName; }
set { this.SetField(ref this.uriName, value); }
}
protected void SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
{
if (!EqualityComparer<T>.Default.Equals(field, value))
{
field = value;
RaiseEventPropertyChanged(propertyName);
}
}
private void RaiseEventPropertyChanged(string propertyName)
{
var tmpEvent = this.PropertyChanged;
if (tmpEvent != null)
{
tmpEvent(this, new PropertyChangedEventArgs(propertyName));
}
}
现在,只要程序更改了绑定源中的对象,显示就会自动更新,如果操作员更改了显示,则会更新bindingsource中的项目,并通过事件通知您的程序