链接 ObservableCollection 和 List<T>

Ton*_*nti 2 .net c# data-binding collections wpf

我是 WPF 中数据绑定的新手,需要一些帮助。

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

我这样做的正确流程是什么?我尝试将 ListBox 绑定到 ObservableCollection。这种方法之所以有效,是因为每当我向 ObservableCollection 添加某些内容时,列表框都会更新,但是,这些添加不会保留到列表中。如何将 ObservableCollection“绑定”到列表,以便当我向 ObservableCollection 添加某些内容时,我真的将其添加到列表中?

提前致谢!

小智 6

ObservableCollection 具有采用 IEnumerable 的构造函数

ObservableCollection<int> myCollection = new ObservableCollection<int>(myList);
Run Code Online (Sandbox Code Playgroud)

因此,您可以在列表上创建一个 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, item));
            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, _internalList[index], index));
        }

        public T this[Int32 index]
        {
            get { return _internalList[index]; }
            set { _internalList[index] = value; }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)