zoukankan      html  css  js  c++  java
  • windows phone listbox虚拟化(下)

       之前写过一篇关于listbox虚拟化的文章,那里采用的方法都是自己早期研究的一些思路,然后发现当数据很大的时候,其实性能效果还是不太理想,下面让我们来仔细想一想到底是基于什么原因,我们回去破坏默认的虚拟化呢?首先一个原因就是下来刷新的问题:由于listbox默认是不支持刷新效果的,这个时候我们可能回去重新自定义listbox,但是我们一旦重写listbox就有可能带来虚拟化的问题,针对这一问题,现在比较好的解决方法就是:乱世经典博客,这种方法并不是像现在很多网路通用的listbox刷新,重写三个自定义控件,它里面只是通过切换不同的VisualStateGroup,这样的话listbox的itemplans就还是支持虚拟化的面板。既然刷新的问题,我们有很好的办法解决虚拟化。那么还有其他的原因会让我们破坏虚拟化吗?肯定是有的,就是当整个页面列表的布局很复杂时候,这种情况下我们可能需要在listbox里面放置自定义控件,一旦你放置usercontrol的话,虚拟化就被破坏了,比如有的时候,我们可能需要listbox里面嵌套listbox这个时候虚拟化肯定是不行的,其实这种情况也有一种很好的解决办法就是:阿干@.NET的博客,在这里面我们可以看到针对listbox里面嵌套listbox的情况,我们可以使用itemcontrols,这样一来的话,它的itempanels就还是虚拟化面板,因此虚拟化还是没有被破坏掉的。

      其实还有一种变态的情况就是有的时候我们需要listbox显示的数据是横排的,通常我们的做法就是:

     <ListBox.ItemsPanel>
                    <ItemsPanelTemplate>                  
                        <toolkit:WrapPanel></toolkit:WrapPanel>                 
                    </ItemsPanelTemplate>
                </ListBox.ItemsPanel>
    

     这样一来的话,就必然会导致虚拟化被破坏,因为你连面板都换掉了。那么针对这种情况有没有好的解决办法呢?其实阿干那篇博客里面就提供了好的解决办法,我们可以自己去实现分列显示的效果,核心的代码是:

    using System;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Ink;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.Diagnostics;
    
    namespace MoHoo.MultiColumnListBox.Demo
    {
        public class RowAdapter<TItemType> : IList<IEnumerable<TItemType>>, INotifyCollectionChanged
        {
            private readonly IList<TItemType> _sourceList;
            private readonly int _columns;
    
            public IList<TItemType> SourceList
            {
                get { return _sourceList; }
            } 
    
            private class RowObject : IEnumerable<TItemType>
            {
                internal readonly RowAdapter<TItemType> Parent;
                internal readonly int StartIndex;
    
                public RowObject(RowAdapter<TItemType> parent, int startIndex)
                {
                    Parent = parent;
                    StartIndex = startIndex;
                }
    
                #region IEnumerable<TItemType> Members
    
                public IEnumerator<TItemType> GetEnumerator()
                {
                    int limit = Parent._sourceList.Count;
                    int end = Math.Min(StartIndex + Parent._columns, limit);
    
                    for (int pos = StartIndex; pos < end; ++pos)
                    {
                        yield return Parent._sourceList[pos];
                    }
                }
    
                #endregion
    
                #region IEnumerable Members
    
                System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
                {
                    return GetEnumerator();
                }
    
                #endregion
            }
    
            public RowAdapter(IList<TItemType> sourceList, int columns)
            {
                if (null == sourceList)
                    throw new ArgumentNullException("sourceList", "Resource.RowAdapter_RowAdapter_sourceList_is_null");
                if (columns <= 0)
                    throw new ArgumentOutOfRangeException("columns", "Resource.RowAdapter_RowAdapter_ColumnsGreaterOne");
    
                // We require the source list to implement IList because we
                // need to know how many item there are
                _sourceList = sourceList;
                _columns = columns;
    
                var sourceNotify = sourceList as INotifyCollectionChanged;
                if (null != sourceNotify)
                {
                    sourceNotify.CollectionChanged += OnSourceCollectionChanged;
                }
            }
    
            #region IList<IEnumerable<TItemType>> Members
    
            public int IndexOf(IEnumerable<TItemType> item)
            {
                var realItem = item as RowObject;
                if (null == realItem || !ReferenceEquals(realItem.Parent, this))
                    return -1;          // It does not belong to this collection
    
                Debug.Assert(0 == realItem.StartIndex % _columns, "RowObject item has a wierd index");
                return realItem.StartIndex / _columns;
            }
    
            public void Insert(int index, IEnumerable<TItemType> item)
    
            {
                throw new NotSupportedException();
            }
    
            public IEnumerable<TItemType> this[int index]
            {
                get
                {
                    if (index < 0 || index > Count)
                        return null;
    
                    return InternalGetRow(index);
                }
                set
                {
                    throw new NotSupportedException();
                }
            }
    
            public void RemoveAt(int index)
            {
                throw new NotSupportedException();
            }
    
            #endregion
    
            #region ICollection<IEnumerable<TItemType>> Members
    
            public void Add(IEnumerable<TItemType> item)
            {
                throw new NotSupportedException();
            }
    
            public bool Contains(IEnumerable<TItemType> item)
            {
                var realItem = item as RowObject;
                return null != realItem && object.ReferenceEquals(realItem.Parent, this);
            }
    
            public void CopyTo(IEnumerable<TItemType>[] array, int arrayIndex)
            {
                // I haven't implemented this. It is easy to implement if you need it
                throw new NotImplementedException();
            }
    
            public bool Remove(IEnumerable<TItemType> item)
            {
                throw new NotSupportedException();
            }
            public void Clear()
            {
                throw new NotSupportedException();
            }
    
            public int Count
            {
                get
                {
                    return (_sourceList.Count + (_columns - 1)) / _columns;
                }
            }
    
            public bool IsReadOnly
            {
                get { return true; }
            }
    
            #endregion
    
            #region IEnumerable<IEnumerable<TItemType>> Members
    
            public IEnumerator<IEnumerable<TItemType>> GetEnumerator()
            {
                for (int i = 0; i < Count; ++i)
                {
                    yield return InternalGetRow(i);
                }
            }
    
            #endregion
    
            #region IEnumerable Members
    
            System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
            {
                return GetEnumerator();
            }
    
            #endregion
    
            #region INotifyCollectionChanged Members
    
            public event NotifyCollectionChangedEventHandler CollectionChanged;
    
            private void FireCollectionChanged()
            {
    
                var handler = CollectionChanged;
                if (null != handler)
                {
                    handler(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
                }
            }
    
            private void OnSourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
            {
                FireCollectionChanged();
            }
    
            #endregion
    
            private RowObject InternalGetRow(int index)
            {
                return new RowObject(this, index * _columns);
            }
        }
    }
    View Code

    这里面的核心思想就是自定义一个索引器。

  • 相关阅读:
    算法导论课后习题解析 第六章
    算法导论课后习题解析 第二章
    如果你也是.NET程序员
    查询对象模式
    为什么要面向对象呢
    HTTP强缓存和协商缓存 F
    MFC Dialog改变大小后,控件随之改变方法
    关于C++类型萃取
    docker配置docker
    idea 全局搜索(Ctrl+Shift+F)不能使用解决办法
  • 原文地址:https://www.cnblogs.com/xiaocai20091687/p/3641719.html
Copyright © 2011-2022 走看看