WinForms数据绑定到集合属性(例如计数)

4

我想要将数据绑定到一个集合属性上,例如Count。

通常情况下,当我进行数据绑定时,我会为集合中的对象属性指定数据成员,而不是实际属性集合本身暴露的属性。

例如,我有一个自定义对象列表。我在DataGridView中展示它们。但我还想使用单独的标签显示它们的总数。是否可以通过数据绑定来实现这一点?

我想象中,我需要以某种方式强制使用PropertyManager,而不是CurrentyManager?

我收到以下异常。请注意,DataSource是集合并具有TotalValue属性。

System.ArgumentException: 无法绑定到DataSource上的属性或列TotalValue。
参数名: dataMember
   at System.Windows.Forms.BindToObject.CheckBinding()
   at System.Windows.Forms.Binding.SetListManager(BindingManagerBase bindingManagerBase)
   at System.Windows.Forms.ListManagerBindingsCollection.AddCore(Binding dataBinding)
   at System.Windows.Forms.BindingsCollection.Add(Binding binding)
   at System.Windows.Forms.BindingContext.UpdateBinding(BindingContext newBindingContext, Binding binding)
   at System.Windows.Forms.Binding.SetBindableComponent(IBindableComponent value)
   at System.Windows.Forms.ControlBindingsCollection.AddCore(Binding dataBinding)
   at System.Windows.Forms.BindingsCollection.Add(Binding binding)
3个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
2
如果您的数据源实现了IList接口,例如BindingList,则绑定会尝试绑定到列表内部元素的属性。 假设您有一个string项目列表,则单个元素没有名为Count的属性。 将您的列表包装到一个类中,该类委托了Count属性而不实现IList接口,并在BindingList触发ListChanged事件时触发PropertyChanged事件。
class CountWrapper : INotifyPropertyChanged
{
    private readonly IBindingList bindingList;

    public CountWrapper(IBindingList bindingList)
    {
        this.bindingList = bindingList;

        bindingList.ListChanged += BindingList_ListChanged;
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public int Count
    {
        get { return bindingList.Count; }
    }

    private void BindingList_ListChanged(object sender, ListChangedEventArgs e)
    {
        var handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(string.Empty));
    }
}
现在,您可以像这样绑定Count属性:
myLabel.DataBindings.Add("Text", new CountWrapper(myObjectList), "Count");
这对其他属性也是可行的,只需为您特定的类使用特定的包装器。如果您的类实现了INotifyPropertyChanged来监听自己的属性,您只需要监听该事件并将其转发即可。
class MyListWrapper : INotifyPropertyChanged
{
    private readonly MyList bindingList;

    public MyListWrapper(MyList bindingList)
    {
        this.bindingList = bindingList;

        bindingList.ListChanged += BindingList_ListChanged;
        bindingList.PropertyChanged+= BindingList_PropertyChanged;
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public int Count
    {
        get { return bindingList.Count; }
    }

    public int TotalCount
    {
        get { return bindingList.TotalCount; }
    }

    public string ReadWriteProperty
    {
        get { return bindingList.ReadWriteProperty; }
        set { bindingList.ReadWriteProperty = value; }
    }


    private void OnPropertyChanged(PropertyChangedEventArgs ea)
    {
        var handler = PropertyChanged;
        if (handler != null) handler(this, ea);
    }

    private void BindingList_ListChanged(object sender, ListChangedEventArgs e)
    {
        OnPropertyChanged(new PropertyChangedEventArgs(string.Empty));
    }

    private void BindingList_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        OnPropertyChanged(e);
    }
}

0

您可以通过在DataBindings.Add方法中指定collection.Count作为dataSource来绑定到集合的Count。 dataMember参数将是一个空字符串。

myLabel.DataBindings.Add("Text", myObjectList.Count, string.Empty);

1
这不会绑定 myObjectList.Count 属性。相反,它绑定了 Count 属性的整数值。这意味着绑定将不再更新。这是一个静态绑定。 - Sriram Sakthivel

0

我认为没有任何理由阻止你将一个文本框(TextBox)与myObjectList.Count绑定,但是必须在myobjectList上实现IBindingList<T>,无论它是自定义集合还是作为BindingList<T>的类型。 IBingingList<T>包含在集合中添加、删除或更改对象时触发的事件。

请参阅MSDN文档BindingListIBindingList。 由于后者有许多成员需要实现,因此您可能希望使用前者。


@Josh Kodroff,实际上我的objectList是一个BindingList。我可以绑定到集合中项的属性,但不能绑定到实际列表的属性(例如Count)。对于TextBox,我可以指定集合中项的属性,TextBox将绑定到集合中的第一个项。当我尝试绑定到List属性时,会出现异常。 - Sumrak
你能否将你遇到的异常添加到帖子中吗? - Josh Kodroff
@Jesh Kodroff:添加了异常文本。 - Sumrak

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,