链接ObservableCollection和List <t>

时间:2016-03-13 11:47:40

标签: c# .net wpf data-binding collections

我是WPF中数据绑定的新手,可以使用一些帮助。

A有一个具有List成员的常规类。我需要显示一个ListBox,其中包含所有这些项目,并在项目添加到该成员时更新。

我这样做的正确过程是什么? 我已经尝试将ListBox绑定到ObservableCollection。这种方式有效,因为每当我向ObservableCollection添加内容时,列表框都会更新,但是这些添加不会持久保存到List。我如何&#34;绑定&#34;一个ObservableCollection到一个列表,这样当我向ObservableCollection添加一些内容时,我真的将它添加到列表中?

提前致谢!

2 个答案:

答案 0 :(得分:1)

ObservableCollection具有构造函数,该构造函数采用IEnumerable

ObservableCollection<int> myCollection = new ObservableCollection<int>(myList);

因此,您可以在List上创建一个ObservableCollection,并且仅对此集合进行操作。完成所有操作后,您可以将ObservableCollection转换回List。

但更简单的是用ObservableCollection替换原始List并直接绑定它。

如果需要更改原始列表,则必须编写实现INotifyCollectionChanged的包装器。

您可以尝试我的代码段:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
using System.Text;

namespace ObservableCollectionListCheck
{
    class Program
    {
        static void Main(string[] args)
        {
            var list = new List<string>();
            var oc = new ObservableWrapper<string>(list);
            oc.CollectionChanged += OnCollectionChanged;

            list.AddRange(new [] {"1","2","3"});

            Console.WriteLine($"List: {string.Join(" ",list)}");            
            Console.WriteLine($"ObservableWrapper: {string.Join(" ", oc)}");

            oc.Add("4");

            Console.WriteLine($"List: {string.Join(" ", list)}");
            Console.WriteLine($"ObservableWrapper: {string.Join(" ", oc)}");

            list.Add("5"); // OnCollectionChanged will not call

            Console.WriteLine($"List: {string.Join(" ", list)}");
            Console.WriteLine($"ObservableWrapper: {string.Join(" ", oc)}");

            Console.ReadLine();
        }

        private static void OnCollectionChanged(Object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs)
        {
            Console.WriteLine($"OnCollectionChanged:{notifyCollectionChangedEventArgs.Action}");
        }
    }

    public class ObservableWrapper<T> : IList<T>, INotifyCollectionChanged
    {
        private readonly IList<T> _internalList;

        public event NotifyCollectionChangedEventHandler CollectionChanged;
        private void RaiseCollectionChanged(object sender, NotifyCollectionChangedEventArgs args)
        {
            CollectionChanged?.Invoke(sender, args);
        }

        public ObservableWrapper(IList<T> list)
        {
            _internalList = list;
        }

        public IEnumerator<T> GetEnumerator()
        {
            return _internalList.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        public void Add(T item)
        {
            _internalList.Add(item);
            RaiseCollectionChanged(this,new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add,item));
        }

        public void Clear()
        {
            _internalList.Clear();
            RaiseCollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
        }

        public Boolean Contains(T item)
        {
            return _internalList.Contains(item);
        }

        public void CopyTo(T[] array, Int32 arrayIndex)
        {
            _internalList.CopyTo(array,arrayIndex);
        }

        public Boolean Remove(T item)
        {
            var result = _internalList.Remove(item);
            RaiseCollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove));
            return result;
        }

        public Int32 Count => _internalList.Count;


        public Boolean IsReadOnly => false;

        public Int32 IndexOf(T item) => _internalList.IndexOf(item);

        public void Insert(Int32 index, T item)
        {
            _internalList.Insert(index,item);
            RaiseCollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add,item,index));
        }

        public void RemoveAt(Int32 index)
        {
            _internalList.RemoveAt(index);
            RaiseCollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove));
        }

        public T this[Int32 index]
        {
            get { return _internalList[index]; }
            set { _internalList[index] = value; }
        }
    }
}

答案 1 :(得分:1)

没有办法将ObservableCollection“绑定”到List,因为“bind”不是IList合约的一部分。 从“按合同设计的角度”来看,有两个接口声明您将获得有关对象更改的通知--InotifyPropertyChanged和INotifyCollectionChanged,而List不实现它们。 你可以自己实现它们,但重新发明轮子是没有意义的,所以最好直接使用ObservableCollection而不是list,就像其他人建议的那样。