WPF:是否有可能多次在ItemsControl上显示一个项目?
我想创建一个控件,但我真的不知道如何用英文来命名它,这就是为什么我不知道该如何谷歌。WPF:是否有可能多次在ItemsControl上显示一个项目?
因此,如果已经有它的名称和/或如果已经有一个具有以下功能的控件,请让我知道。
我的控制是某种ItemsControl
,但有一个区别。如果它包含的项目太少而无法完全填充视口,则应该再次从第一个项目开始,直到视口完全填充。所以,如果视口有空间让我们说五个项目,并且我的ItemsSource
只包含两个项目,控件应该显示项目1,然后是2,然后是1,然后是2,然后是1再次显示1。回到顶端这篇文章中的信息适用于:????????????????
把它看作是电视新闻频道底部的新闻频道的WPF等价物。它围绕着可用的物品进行盘旋,如果它到达终点,它将再次从第一个物品开始,两者之间没有间隙。
我已经尝试为此创建自己的面板,但我找不到在此面板中多次显示一个项目的方法。这甚至有可能吗?
你将如何创建这样的控制?我可以基于默认ItemsControl
或我必须从Control
继承,并从头开始?
谢谢你的想法和推动正确的方向。
编辑1:
我尝试了以下遵循建议的答复1.
我创建了一个RecurringEnumerator(Of T)
:
Imports System.Collections.ObjectModel
Public Class RecurringEnumerator(Of T)
Implements IEnumerator(Of T)
Private _internal As ICollection(Of T)
Private _currentIndex As Integer
Public Sub New(ByVal internal As ICollection(Of T))
If (internal Is Nothing) Then
Throw New ArgumentNullException("internal")
End If
_internal = internal
_currentIndex = -1
End Sub
Public ReadOnly Property Current As T Implements IEnumerator(Of T).Current
Get
Return _internal(_currentIndex)
End Get
End Property
Public ReadOnly Property CurrentObject As Object Implements IEnumerator.Current
Get
Return _internal(_currentIndex)
End Get
End Property
Public Function MoveNext() As Boolean Implements IEnumerator.MoveNext
If (_internal.Count = 0) Then
Return False
End If
_currentIndex += 1
If (_currentIndex >= _internal.Count) Then
_currentIndex -= _internal.Count
End If
Return True
End Function
Public Sub Reset() Implements IEnumerator.Reset
_currentIndex = -1
End Sub
Public Sub Dispose() Implements IDisposable.Dispose
End Sub
End Class
然后我在用这个RecurringEnumerator(Of T)
RecurringCollection(Of T)
: 公共类RecurringCollection(Of T) 实施ICollection (OF T)
Private _enumerator As RecurringEnumerator(Of T)
Private _internal As ObjectModel.Collection(Of T)
Public Sub New()
_enumerator = New RecurringEnumerator(Of T)(Me)
_internal = New ObjectModel.Collection(Of T)
End Sub
Public Function GetEnumerator() As IEnumerator(Of T) Implements IEnumerable(Of T).GetEnumerator
Return _enumerator
End Function
Public Function GetObjectEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
Return _enumerator
End Function
Public Sub Add(ByVal item As T) Implements ICollection(Of T).Add
_internal.Add(item)
End Sub
Public Sub Clear() Implements ICollection(Of T).Clear
_internal.Clear()
End Sub
Public Function Contains(ByVal item As T) As Boolean Implements ICollection(Of T).Contains
Return _internal.Contains(item)
End Function
Public Sub CopyTo(ByVal array() As T, ByVal arrayIndex As Integer) Implements ICollection(Of T).CopyTo
_internal.CopyTo(array, arrayIndex)
End Sub
Public ReadOnly Property Count As Integer Implements ICollection(Of T).Count
Get
Return _internal.Count
End Get
End Property
Public ReadOnly Property IsReadOnly As Boolean Implements ICollection(Of T).IsReadOnly
Get
Return False
End Get
End Property
Public Function Remove(ByVal item As T) As Boolean Implements ICollection(Of T).Remove
Return _internal.Remove(item)
End Function
End Class
但是把三个短字符串这个RecurringCollection(Of T)
内部和换eaching通过收集和显示每个串的消息框导致了StackOverflowException
没有示出至少一个消息框。
我之前没有创建自定义集合,所以我不确定我是否做得正确。
而不是试图操纵ItemsControl
你可以创建一个专门的集合。我在下面写了一个模板。为了简洁起见,我省略了错误检查和其他ICollection<T>
方法。您可以轻松将这些方法委托给内部列表。
public class RecurringList<T> : ICollection<T>
{
private readonly List<T> _items = new List<T>();
public int DesiredCount { get; set; }
public int Count => _items.Count > 0 ? DesiredCount : 0;
public bool IsReadOnly => false;
public IEnumerator<T> GetEnumerator()
{
if (_items.Count == 0)
{
yield break;
}
int count = Math.Max(DesiredCount, _items.Count);
for (int i = 0; i < count; i++)
{
yield return _items[i % _items.Count];
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void Add(T item)
{
_items.Add(item);
}
public void Clear()
{
_items.Clear();
}
public bool Contains(T item)
{
return _items.Contains(item);
}
public void CopyTo(T[] array, int arrayIndex)
{
_items.CopyTo(array, arrayIndex);
}
public bool Remove(T item)
{
return _items.Remove(item);
}
}
@Downvoter Care to comment? –
我不是downvoter! 我试过你的解决方案,但是你的代码没有工作,比如你的函数'GetEnumerator'返回的是Type T的值,但是应该返回'IEnumerator'。 请参阅我的编辑问题,而不是我尝试的。 –
Nostromo
我试过这个解决方案,它运行良好。 'GetEnumerator'函数** yield **返回'T'。这是C#的'IEnumerable'模式。你可以看到一个解释[这里](http://james-ramsden.com/implement-ienumerable-c/)。 –