【问题标题】:Bindingsource cannot be its own data sourceBindingsource 不能是它自己的数据源
【发布时间】:2015-07-08 08:48:21
【问题描述】:

当我从 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);
            }
        }

【问题讨论】:

    标签: c# datagridview uri bindingsource bindinglist


    【解决方案1】:

    绑定源用于将数据绑定到显示的数据。在您的情况下,显示的数据是数据网格视图。

    如果您决定使用绑定源作为 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 的列表:

    • 创建新的 Windows 窗体应用程序
    • 使用工具箱添加 BindingSource
    • BindingSource 属性 DataSource = MyDisplayableUriString
    • 使用工具箱添加 DataGridView
    • DataGridView 属性:DataSource = BindingSource1

    您应该会看到 MyDisplayableUriString 的字段显示在 DataGridView 中。

    • 使用属性窗口作为表单加载时的事件处理程序

    在这个事件处理程序中,用几个 Displayable 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 = "约翰"; }

    现在,如果您运行程序并单击按钮,则名称不会更新。

    原因是你的类没有实现 INotifyPropertyChanged。因此,当 uri 项目更改时,绑定源不会收到通知。因此 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));
        }
    }
    

    现在,当您的程序更改绑定源中的对象时,显示会自动更新,如果操作员更改显示,绑定源中的项目也会更新,并且您的程序会通过事件获得有关更改的通知

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-04-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多