Lou*_*ann 5 wpf linked-list inotifycollectionchanged
在我的 WPF 应用程序中,我有一个 ItemsControl,其项目值取决于上一个显示的项目。
ViewModel 是一个分割成可变长度部分的音频文件,我需要以这种方式显示它,右边显示一个 DateTime,这就是我需要计算的(我只知道每个部分的长度,我需要计算它开始和结束的实际时间,以及 ItemsControl 上的位置)。
--
----
------------
--
--------------------
Run Code Online (Sandbox Code Playgroud)
我的第一种方法是使用一个,ObservableCollection<MyviewModel>但很快就发生了一些恐怖事件:
5 路多重绑定,其中IMultiValueConverter我计算要返回的值并将 DataContext 的属性设置为该值,因为我只在运行时知道前一个元素。
前一个元素是使用 上的绑定发送的Relativesource.PreviousData。
现在我的问题是,在从 Converter 设置一个值(这显然是一件坏事)并实际让它工作后,常规 Collection 在其元素中没有顺序的概念,所以当更进一步时我想在其余部分中间添加一个音频部分,显示混乱。
此外,当我实现更多业务逻辑时,我可能需要访问在此转换器中计算的音频部分的开始和结束,如果还没有显示怎么办......?
所以这种方法在几个层面上都是错误的。
这就是我开始使用谷歌搜索并发现关于LinkedList. 现在我正在尝试创建一个基本上是 Observable LinkedList 的类(我不需要它是通用的):
public class ObservableSegmentLinkedList : LinkedList<MyViewModel>, INotifyCollectionChanged
{
//Overrides ???
#region INotifyCollectionChanged Members
public event NotifyCollectionChangedEventHandler CollectionChanged;
public void OnNotifyCollectionChanged(NotifyCollectionChangedEventArgs e)
{
if (CollectionChanged != null)
{
CollectionChanged(this, e);
}
}
#endregion
}
Run Code Online (Sandbox Code Playgroud)
问题的核心是我无法覆盖修改集合的方法(Addfirst、AddLast 等),所以我无法正确调用 OnNotifyCollectionChanged...
所以我想我可以为这些方法中的每一个做重载,但这听起来很讨厌......
简而言之:我需要某种集合,其中每个项目都知道前一个项目的详细信息,以便计算其自己的一个属性。
有什么线索吗?这甚至是一个很好的解决方案吗?
谢谢!
附录,ViewModel 看起来像:
public class MyViewModel : INotifyPropertyChanged
{
private DateTime m_SegmentLength;
public DateTime SegmentLength
{
get { return m_SegmentLength; }
set
{
m_SegmentLength = value;
NotifyPropertyChanged("SegmentLength");
}
}
private DateTime m_SegmentAdvert;
public DateTime SegmentAdvert
{
get { return m_SegmentAdvert; }
set
{
m_SegmentAdvert = value;
NotifyPropertyChanged("SegmentAdvert");
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String prop)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(prop));
}
#endregion
}
Run Code Online (Sandbox Code Playgroud)
编辑:我想我会尝试结合 Thomas 和 Will 的答案:我将使用组合(即,我将 LinkedList 的实例保留在我的自定义对象中,而不是从它继承)并重新定义要使用的方法(AddAfter、AddFirst等),其中我将在调用实际的 LinkedList 方法后调用 OnNotifyPropertychanged。这有点工作,但我想我的问题不会有任何优雅的解决方案......
现在,我创建了一个自定义泛型类,该类支持IEnumerable并像 . 一样LinkedList<T>使用,唯一的区别是 WPF 会收到更改通知。
请注意,此解决方案仅适用于相当小的集合,我最多只需要管理大约 30 个元素,因此对我来说很好,但是每次修改此集合时,它都会被视为“重置”。
解决方法如下:
/// <summary>
/// This class is a LinkedList that can be used in a WPF MVVM scenario. Composition was used instead of inheritance,
/// because inheriting from LinkedList does not allow overriding its methods.
/// </summary>
/// <typeparam name="T"></typeparam>
public class ObservableLinkedList<T> : INotifyCollectionChanged, IEnumerable
{
private LinkedList<T> m_UnderLyingLinkedList;
#region Variables accessors
public int Count
{
get { return m_UnderLyingLinkedList.Count; }
}
public LinkedListNode<T> First
{
get { return m_UnderLyingLinkedList.First; }
}
public LinkedListNode<T> Last
{
get { return m_UnderLyingLinkedList.Last; }
}
#endregion
#region Constructors
public ObservableLinkedList()
{
m_UnderLyingLinkedList = new LinkedList<T>();
}
public ObservableLinkedList(IEnumerable<T> collection)
{
m_UnderLyingLinkedList = new LinkedList<T>(collection);
}
#endregion
#region LinkedList<T> Composition
public LinkedListNode<T> AddAfter(LinkedListNode<T> prevNode, T value)
{
LinkedListNode<T> ret = m_UnderLyingLinkedList.AddAfter(prevNode, value);
OnNotifyCollectionChanged();
return ret;
}
public void AddAfter(LinkedListNode<T> node, LinkedListNode<T> newNode)
{
m_UnderLyingLinkedList.AddAfter(node, newNode);
OnNotifyCollectionChanged();
}
public LinkedListNode<T> AddBefore(LinkedListNode<T> node, T value)
{
LinkedListNode<T> ret = m_UnderLyingLinkedList.AddBefore(node, value);
OnNotifyCollectionChanged();
return ret;
}
public void AddBefore(LinkedListNode<T> node, LinkedListNode<T> newNode)
{
m_UnderLyingLinkedList.AddBefore(node, newNode);
OnNotifyCollectionChanged();
}
public LinkedListNode<T> AddFirst(T value)
{
LinkedListNode<T> ret = m_UnderLyingLinkedList.AddFirst(value);
OnNotifyCollectionChanged();
return ret;
}
public void AddFirst(LinkedListNode<T> node)
{
m_UnderLyingLinkedList.AddFirst(node);
OnNotifyCollectionChanged();
}
public LinkedListNode<T> AddLast(T value)
{
LinkedListNode<T> ret = m_UnderLyingLinkedList.AddLast(value);
OnNotifyCollectionChanged();
return ret;
}
public void AddLast(LinkedListNode<T> node)
{
m_UnderLyingLinkedList.AddLast(node);
OnNotifyCollectionChanged();
}
public void Clear()
{
m_UnderLyingLinkedList.Clear();
OnNotifyCollectionChanged();
}
public bool Contains(T value)
{
return m_UnderLyingLinkedList.Contains(value);
}
public void CopyTo(T[] array, int index)
{
m_UnderLyingLinkedList.CopyTo(array, index);
}
public bool LinkedListEquals(object obj)
{
return m_UnderLyingLinkedList.Equals(obj);
}
public LinkedListNode<T> Find(T value)
{
return m_UnderLyingLinkedList.Find(value);
}
public LinkedListNode<T> FindLast(T value)
{
return m_UnderLyingLinkedList.FindLast(value);
}
public Type GetLinkedListType()
{
return m_UnderLyingLinkedList.GetType();
}
public bool Remove(T value)
{
bool ret = m_UnderLyingLinkedList.Remove(value);
OnNotifyCollectionChanged();
return ret;
}
public void Remove(LinkedListNode<T> node)
{
m_UnderLyingLinkedList.Remove(node);
OnNotifyCollectionChanged();
}
public void RemoveFirst()
{
m_UnderLyingLinkedList.RemoveFirst();
OnNotifyCollectionChanged();
}
public void RemoveLast()
{
m_UnderLyingLinkedList.RemoveLast();
OnNotifyCollectionChanged();
}
#endregion
#region INotifyCollectionChanged Members
public event NotifyCollectionChangedEventHandler CollectionChanged;
public void OnNotifyCollectionChanged()
{
if (CollectionChanged != null)
{
CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
}
#endregion
#region IEnumerable Members
IEnumerator IEnumerable.GetEnumerator()
{
return (m_UnderLyingLinkedList as IEnumerable).GetEnumerator();
}
#endregion
}
Run Code Online (Sandbox Code Playgroud)
正如@AndrewS 在评论中提到的,LinkedListNode 应该替换为自定义类,该类从其 List 属性返回 ObservableLinkedList。
| 归档时间: |
|
| 查看次数: |
5404 次 |
| 最近记录: |