我想创建一个控件,但我真的不知道怎么用英文命名它,这就是为什么我真的不知道谷歌要用什么。
所以,如果已经有了它的名称和/或如果已经有一个具有以下功能的控件,请告诉我。
我的控制是某种ItemsControl
,但有一点不同。如果它包含的项目太少而无法完全填充视口,则它应该再次从第一个项目开始,直到视口完全填满。
因此,如果视口有空间让我们说五个项目,而我的ItemsSource
只包含两个项目,那么控件应该显示项目1,然后是2,然后是1,然后是2,然后是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)
中加入三个短字符串,并在整个集合中分别显示每个字符串的消息框,结果显示StackOverflowException
而没有显示至少一个消息框。
之前我没有创建自定义集合,所以我不确定我是否做得对。
答案 0 :(得分:-1)
您可以创建专门的集合,而不是尝试操纵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);
}
}