有像UITableView这样的东西吗?

时间:2014-05-09 10:05:30

标签: c# .net windows-phone-8

我发现存在列表框,但我找不到如何使用它的好例子。
而且当我滚动到我的ListBox底部时,我可以做一些事情,我需要添加新行,当用户点击行时我也需要做一些逻辑。

有可能吗?

1 个答案:

答案 0 :(得分:0)

是的,这是可能的。 要使滚动到达底部时加载项的ListBox,必须实现一个名为LazyList的东西。 我自己也做过类似的事情。

您可以将此LazyCollection用作ListBox的数据源:

public class LazyCollection<T> : IList<T>, IList, INotifyCollectionChanged, INotifyPropertyChanged
{
    private const int LOAD_THRESHOLD = 3;

    private ObservableCollection<T> _innerCollection;

    public LazyCollection(Func<int, IEnumerable<T>> fetch)
        : this(fetch, null)
    { }

    public LazyCollection(Func<int, IEnumerable<T>> fetch, IEnumerable<T> items)
    {
        _fetch = fetch;
        _innerCollection = new ObservableCollection<T>(items ?? new T[0]);
        this.AttachEvents();
        this.HasMoreItems = true;
    }

    private void AttachEvents()
    {
        _innerCollection.CollectionChanged += (s, e) => OnCollectionChanged(e);
        ((INotifyPropertyChanged)_innerCollection).PropertyChanged += (s, e) => OnPropertyChanged(e);
    }

    #region INotifyPropertyChanged
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
    {
        if (this.PropertyChanged != null)
            this.PropertyChanged(this, e);
    }
    #endregion

    #region INotifyCollectionChanged
    public event NotifyCollectionChangedEventHandler CollectionChanged;
    protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
    {
        if (this.CollectionChanged != null)
            this.CollectionChanged(this, e);
    }
    #endregion

    #region IList<T>
    public int IndexOf(T item)
    {
        return _innerCollection.IndexOf(item);
    }

    public void Insert(int index, T item)
    {
        _innerCollection.Insert(index, item);
    }

    public void RemoveAt(int index)
    {
        _innerCollection.RemoveAt(index);
    }

    public T this[int index]
    {
        get
        {
            Debug.WriteLine("LazyCollection - Reading item {0}", index);
            return _innerCollection[index];
        }
        set { _innerCollection[index] = value; }
    }

    public void Add(T item)
    {
        _innerCollection.Add(item);
    }

    public void Clear()
    {
        _innerCollection.Clear();
    }

    public bool Contains(T item)
    {
        return _innerCollection.Contains(item);
    }

    public void CopyTo(T[] array, int arrayIndex)
    {
        _innerCollection.CopyTo(array, arrayIndex);
    }

    public int Count
    {
        get { return _innerCollection.Count; }
    }

    public bool IsReadOnly
    {
        get { return ((IList<T>)_innerCollection).IsReadOnly; }
    }

    public bool Remove(T item)
    {
        return _innerCollection.Remove(item);
    }

    public IEnumerator<T> GetEnumerator()
    {
        Debug.WriteLine("LazyCollection - GetEnumerator");
        return _innerCollection.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        Debug.WriteLine("LazyCollection - GetEnumerator explicit");
        return ((IEnumerable)_innerCollection).GetEnumerator();
    }
    #endregion

    #region IList
    int IList.Add(object value)
    {
        return ((IList)_innerCollection).Add(value);
    }

    bool IList.Contains(object value)
    {
        return ((IList)_innerCollection).Contains(value);
    }

    int IList.IndexOf(object value)
    {
        return ((IList)_innerCollection).IndexOf(value);
    }

    void IList.Insert(int index, object value)
    {
        ((IList)_innerCollection).Insert(index, value);
    }

    bool IList.IsFixedSize
    {
        get { return ((IList)_innerCollection).IsFixedSize; }
    }

    bool IList.IsReadOnly
    {
        get { return ((IList)_innerCollection).IsReadOnly; }
    }

    void IList.Remove(object value)
    {
        ((IList)_innerCollection).Remove(value);
    }

    object IList.this[int index]
    {
        get
        {
            if (index > this.Count - LOAD_THRESHOLD)
            {
                this.TryLoadMoreItems();
            }

            Debug.WriteLine("LazyCollection - Reading item {0} IList", index);
            return ((IList)_innerCollection)[index];
        }
        set { ((IList)_innerCollection)[index] = value; }
    }

    void ICollection.CopyTo(Array array, int index)
    {
        ((IList)_innerCollection).CopyTo(array, index);
    }

    bool ICollection.IsSynchronized
    {
        get { return ((IList)_innerCollection).IsSynchronized; }
    }

    object ICollection.SyncRoot
    {
        get { return ((IList)_innerCollection).SyncRoot; }
    }
    #endregion

    public T[] GetLoadedItems()
    {
        return _innerCollection.ToArray();
    }

    public void ResetLoadedItems(IEnumerable<T> list)
    {
        _innerCollection.Clear();
        foreach (var i in list)
            _innerCollection.Add(i);
        this.HasMoreItems = true;
    }

    public bool HasMoreItems { get; set; }
    private bool _isLoading = false;
    private Func<int, IEnumerable<T>> _fetch;

    private async Task TryLoadMoreItems()
    {
        if (_isLoading || !this.HasMoreItems)
            return;

        try
        {
            _isLoading = true;

            Debug.WriteLine("LazyCollection - Loading more items skip {0}", this.Count);
            List<T> items = _fetch != null ? (_fetch(Count)).ToList() : new List<T>();

            if (items.Count == 0)
            {
                Debug.WriteLine("LazyCollection - No items returned, Loading disabled", this.Count);
                this.HasMoreItems = false;
            }

            items.ForEach(x => _innerCollection.Add(x));

            Debug.WriteLine("LazyCollection - Items added. Total count: {0}", this.Count);
        }
        finally
        {
            _isLoading = false;
        }


    }
}

以下是您使用它的方式

var functionThatProvidesData = (indexFromWhereToStart)=> 
        {
            //Here you do the part that provides data to your List and Skip the items that
            // are already provided and take as many as you decide to take.
            return MyDataSource.Skip(indexFromWhereToStart).Take(30 or more);
        }
LazyCollection<MyObjectType> myDataSource = new LazyCollection<MyObjectType>(functionThatProvidesData);
lboMyListBox.ItemsSource = myDataSource;

关于点击项目的事件,有多种方法可以做到

    关于Tap 中每个项目的
  • ItemTemplate事件 当您单击已选中的项目时,ListBox 上的
  • SelectionChanged不起作用

XAML代码:

<ListBox Margin="50" Name="lboMyListBox" SelectionChanged="lboMyListBox_SelectionChanged">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Grid Margin="15" Tap="Item_Tap">
                <TextBlock Text="{Binding Quantity}" FontSize="40" HorizontalAlignment="Center" VerticalAlignment="Center"/>
                <TextBlock Text="{Binding Price}" FontSize="25" VerticalAlignment="Bottom" HorizontalAlignment="Right"/>
            </Grid>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

注意

您必须在代码中包含您的事件处理程序才能编译XAML。