【问题标题】:WinForms databind to collection property (such as count)WinForms 数据绑定到集合属性(例如计数)
【发布时间】:2011-01-09 16:01:44
【问题描述】:

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

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

例如,我有一个自定义对象列表。我在 datagridview 中显示它们。但我也想使用单独的标签显示他们的总数。有没有办法通过数据绑定来做到这一点?

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

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

System.ArgumentException:无法绑定到数据源上的属性或列 TotalValue。
参数名称:dataMember
   在 System.Windows.Forms.BindToObject.CheckBinding()
   在 System.Windows.Forms.Binding.SetListManager(BindingManagerBase bindingManagerBase)
   在 System.Windows.Forms.ListManagerBindingsCollection.AddCore(绑定数据绑定)
   在 System.Windows.Forms.BindingsCollection.Add(绑定绑定)
   在 System.Windows.Forms.BindingContext.UpdateBinding(BindingContext newBindingContext,绑定绑定)
   在 System.Windows.Forms.Binding.SetBindableComponent(IBindableComponent 值)
   在 System.Windows.Forms.ControlBindingsCollection.AddCore(绑定数据绑定)
   在 System.Windows.Forms.BindingsCollection.Add(绑定绑定)

【问题讨论】:

    标签: .net winforms data-binding


    【解决方案1】:

    如果您的数据源正在实现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);
        }
    }
    

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

      • 这不会绑定myObjectList.Count 属性。相反,它绑定Countproperty 的整数值。这意味着绑定将不再更新。这是一个静态绑定。
      【解决方案3】:

      我认为没有任何理由不能将 TextBox 绑定到 myObjectList.Count,但是 myobjectList 需要单独实现 IBindingList<T>,如果它是带有额外验证的自定义集合,或者是 BindingList<T> 类型。 IBingingList<T> 包含在集合中添加、删除或更改对象时触发的事件。

      请参阅 BindingListIBindingList 上的 MSDN 文档。您可能希望使用前者,因为后者有很多成员要实现。

      【讨论】:

      • @Josh Kodroff,实际上 myobjectList 是一个 BindingList。我可以绑定到集合中项目的属性,但不能绑定到实际列表的属性(例如 Count)。对于 TextBox,我可以指定集合中项目的属性,并且 TextBox 绑定到集合中的第一个项目。当我尝试绑定到 List 属性时,出现异常。
      • 你能在你的帖子中添加你得到的例外吗?
      • @Jesh Kodroff:添加了异常文本
      猜你喜欢
      • 1970-01-01
      • 2011-02-20
      • 2013-03-15
      • 1970-01-01
      • 2012-01-13
      • 2022-01-10
      • 2014-04-06
      • 1970-01-01
      • 2019-11-14
      相关资源
      最近更新 更多