我是WPF中数据绑定的新手,可以使用一些帮助。
A有一个具有List成员的常规类。我需要显示一个ListBox,其中包含所有这些项目,并在项目添加到该成员时更新。
我这样做的正确过程是什么? 我已经尝试将ListBox绑定到ObservableCollection。这种方式有效,因为每当我向ObservableCollection添加内容时,列表框都会更新,但是这些添加不会持久保存到List。我如何"绑定"一个ObservableCollection到一个列表,这样当我向ObservableCollection添加一些内容时,我真的将它添加到列表中?
提前致谢!
答案 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,就像其他人建议的那样。