c# - VirtualizingTilePanel background scrolling -


i'm trying create view looks bookshelf items sitting on shelf virtualization. able achieve adding virtualizingtilepanel class listview. class using dan crevier's blog here: http://blogs.msdn.com/b/dancre/archive/2006/02/16/implementing-a-virtualizingpanel-part-4-the-goods.aspx

i adding virtualizingtilepanel , background listview this:

<listview.itemspanel>     <itemspaneltemplate>         <local:virtualizingtilepanel>             <local:virtualizingtilepanel.background>                 <imagebrush imagesource="..\images\bookshelf.png" alignmentx="left" alignmenty="top" tilemode="tile" stretch="none" viewportunits="absolute" viewport="0,0,319,203" />             </local:virtualizingtilepanel.background>         </local:virtualizingtilepanel>     </itemspaneltemplate> </listview.itemspanel> 

the problem have background fills original visible area. once start scrolling down background moves (like want to) background comes view white.

how can background fill entire scrollable area?

hope makes sense, can add pictures if needed.

edit

my virtualizingtilepanel class:

class virtualizingtilepanel : virtualizingpanel, iscrollinfo {     public virtualizingtilepanel()     {         // use in iscrollinfo implementation         this.rendertransform = _trans;       }      // dependency property controls size of child elements     public static readonly dependencyproperty childsizeproperty        = dependencyproperty.registerattached("childsize", typeof(double), typeof(virtualizingtilepanel),           new frameworkpropertymetadata(168.0d, frameworkpropertymetadataoptions.affectsmeasure |           frameworkpropertymetadataoptions.affectsarrange));       // accessor child size dependency property     public double childsize     {         { return (double)getvalue(childsizeproperty); }         set { setvalue(childsizeproperty, value); }     }      /// <summary>     /// measure children     /// </summary>     /// <param name="availablesize">size available</param>     /// <returns>size desired</returns>     iitemcontainergenerator generator;     protected override size measureoverride(size availablesize)     {         updatescrollinfo(availablesize);          // figure out range that's visible based on layout algorithm         int firstvisibleitemindex, lastvisibleitemindex;         getvisiblerange(out firstvisibleitemindex, out lastvisibleitemindex);          // need access internalchildren before generator work around bug         uielementcollection children = this.internalchildren;         generator = this.itemcontainergenerator;          // generator position of first visible data item         generatorposition startpos = generator.generatorpositionfromindex(firstvisibleitemindex);          // index we'd insert child position. if item realized         // (position.offset == 0), it's position.index, otherwise have add 1         // insert after corresponding child         int childindex = (startpos.offset == 0) ? startpos.index : startpos.index + 1;          using (generator.startat(startpos, generatordirection.forward, true))         {             (int itemindex = firstvisibleitemindex; itemindex <= lastvisibleitemindex; ++itemindex, ++childindex)             {                 bool newlyrealized;                  // or create child                 uielement child = generator.generatenext(out newlyrealized) uielement;                 if (newlyrealized)                 {                     // figure out if need insert child @ end or somewhere in middle                     if (childindex >= children.count)                     {                         base.addinternalchild(child);                     }                     else                     {                         base.insertinternalchild(childindex, child);                     }                     generator.prepareitemcontainer(child);                 }                 else                 {                     // child has been created, let's sure it's in right spot                     debug.assert(child == children[childindex], "wrong child generated");                 }                  // measurements depend on layout algorithm                 child.measure(getchildsize());             }         }          // note: deferred idle time efficiency         cleanupitems(firstvisibleitemindex, lastvisibleitemindex);          return availablesize;     }      /// <summary>     /// arrange children     /// </summary>     /// <param name="finalsize">size available</param>     /// <returns>size used</returns>     protected override size arrangeoverride(size finalsize)     {         iitemcontainergenerator generator = this.itemcontainergenerator;          updatescrollinfo(finalsize);          (int = 0; < this.children.count; i++)         {             uielement child = this.children[i];              // map child offset item offset             int itemindex = generator.indexfromgeneratorposition(new generatorposition(i, 0));              arrangechild(itemindex, child, finalsize);         }          return finalsize;     }      /// <summary>     /// revirtualize items no longer visible     /// </summary>     /// <param name="mindesiredgenerated">first item index should visible</param>     /// <param name="maxdesiredgenerated">last item index should visible</param>     private void cleanupitems(int mindesiredgenerated, int maxdesiredgenerated)     {         uielementcollection children = this.internalchildren;         iitemcontainergenerator generator = this.itemcontainergenerator;          (int = children.count - 1; >= 0; i--)         {             generatorposition childgeneratorpos = new generatorposition(i, 0);             int itemindex = generator.indexfromgeneratorposition(childgeneratorpos);             if (itemindex < mindesiredgenerated || itemindex > maxdesiredgenerated)             {                 generator.remove(childgeneratorpos, 1);                 removeinternalchildrange(i, 1);             }         }     }      /// <summary>     /// when items removed, remove corresponding ui if necessary     /// </summary>     /// <param name="sender"></param>     /// <param name="args"></param>     protected override void onitemschanged(object sender, itemschangedeventargs args)     {         switch (args.action)         {             case notifycollectionchangedaction.remove:             case notifycollectionchangedaction.replace:             case notifycollectionchangedaction.move:                 removeinternalchildrange(args.position.index, args.itemuicount);                 break;         }     }      #region layout specific code     // i've isolated layout specific code region. if want other tiling,     // you'll make changes      int width = 100;     int height = 203;      /// <summary>     /// calculate extent of view based on available size     /// </summary>     /// <param name="availablesize">available size</param>     /// <param name="itemcount">number of data items</param>     /// <returns></returns>     private size calculateextent(size availablesize, int itemcount)     {         int childrenperrow = calculatechildrenperrow(availablesize);          // see how big         return new size(childrenperrow * width,             height * math.ceiling((double)itemcount / childrenperrow));     }      /// <summary>     /// range of children visible     /// </summary>     /// <param name="firstvisibleitemindex">the item index of first visible item</param>     /// <param name="lastvisibleitemindex">the item index of last visible item</param>     private void getvisiblerange(out int firstvisibleitemindex, out int lastvisibleitemindex)     {         int childrenperrow = calculatechildrenperrow(_extent);          firstvisibleitemindex = (int) math.floor(_offset.y / height) * childrenperrow;         lastvisibleitemindex = (int) math.ceiling((_offset.y + _viewport.height) / height) * childrenperrow - 1;          itemscontrol itemscontrol = itemscontrol.getitemsowner(this);         int itemcount = itemscontrol.hasitems ? itemscontrol.items.count : 0;         if (lastvisibleitemindex >= itemcount)             lastvisibleitemindex = itemcount-1;      }      /// <summary>     /// size of children. assume same     /// </summary>     /// <returns>the size</returns>     private size getchildsize()     {         //return new size(this.childsize, this.childsize);         return new size(width, height);     }      /// <summary>     /// position child     /// </summary>     /// <param name="itemindex">the data item index of child</param>     /// <param name="child">the element position</param>     /// <param name="finalsize">the size of panel</param>     private void arrangechild(int itemindex, uielement child, size finalsize)     {         int childrenperrow = calculatechildrenperrow(finalsize);          int row = itemindex / childrenperrow;         int column = itemindex % childrenperrow;          child.arrange(new rect(column * width, row * height, width, height));     }      /// <summary>     /// helper function tiling layout     /// </summary>     /// <param name="availablesize">size available</param>     /// <returns></returns>     private int calculatechildrenperrow(size availablesize)     {         // figure out how many children fit on each row         int childrenperrow;         if (availablesize.width == double.positiveinfinity)             childrenperrow = this.children.count;         else             childrenperrow = math.max(1, (int)math.floor(availablesize.width / width));         return childrenperrow;     }      #endregion      #region iscrollinfo members     private size _extent = new size(0, 0);     private size _viewport = new size(0, 0);     private point _offset;     private translatetransform _trans = new translatetransform();      private void updatescrollinfo(size availablesize)     {         // see how many items there         itemscontrol itemscontrol = itemscontrol.getitemsowner(this);         int itemcount = itemscontrol.hasitems ? itemscontrol.items.count : 0;          size extent = calculateextent(availablesize, itemcount);           // update extent         if (extent != _extent)         {             _extent = extent;              if (_owner != null)                 _owner.invalidatescrollinfo();         }          // update viewport         if (availablesize != _viewport)         {             _viewport = availablesize;             if (_owner != null)                 _owner.invalidatescrollinfo();         }     }      private bool _canhscroll = false;     public bool canhorizontallyscroll     {         { return _canhscroll; }         set { _canhscroll = value; }     }      private bool _canvscroll = false;     public bool canverticallyscroll     {         { return _canvscroll; }         set { _canvscroll = value; }     }      public double extentheight     {         { return _extent.height; }     }      public double extentwidth     {         { return _extent.width; }     }      public double horizontaloffset     {         { return _offset.x; }     }      public double verticaloffset     {         { return _offset.y; }     }       public rect makevisible(visual visual, rect rectangle)     {         return new rect();     }      public void mousewheeldown()     {         pagedown();     }      public void mousewheelleft()     {         throw new invalidoperationexception();     }      public void mousewheelright()     {         throw new invalidoperationexception();     }      public void mousewheelup()     {         pageup();     }      public void pagedown()     {         setverticaloffset(verticaloffset + _viewport.height * 0.1);     }      public void pageleft()     {         sethorizontaloffset(horizontaloffset - _viewport.width * 0.1);     }      public void pageright()     {         sethorizontaloffset(horizontaloffset + _viewport.width * 0.8);     }      public void pageup()     {         setverticaloffset(verticaloffset - _viewport.height * 0.1);     }      private scrollviewer _owner;     public scrollviewer scrollowner     {         { return _owner; }         set { _owner = value; }     }      public void sethorizontaloffset(double offset)     {         if (offset < 0 || _viewport.width >= _extent.width)         {             offset = 0;         }         else         {             if (offset + _viewport.width >= _extent.width)             {                 offset = _extent.width - _viewport.width;             }         }          _offset.x = offset;          if (_owner != null)             _owner.invalidatescrollinfo();          invalidatemeasure();     }      public void setverticaloffset(double offset)     {         if (offset < 0 || _viewport.height >= _extent.height)         {             offset = 0;         }         else         {             if (offset + _viewport.height >= _extent.height)             {                 offset = _extent.height - _viewport.height;             }         }          _offset.y = offset;          if (_owner != null)             _owner.invalidatescrollinfo();          _trans.y = -offset;          invalidatemeasure();     }      public double viewportheight     {         { return _viewport.height; }     }      public double viewportwidth     {         { return _viewport.width; }     }      public void lineup()     {         setverticaloffset(this.verticaloffset - 10);     }      public void linedown()     {         setverticaloffset(this.verticaloffset + 10);     }      public void lineleft()     {         throw new invalidoperationexception();     }      public void lineright()     {         throw new invalidoperationexception();     }      #endregion        #region helper data structures      class itemabstraction     {         public itemabstraction(wrappanelabstraction panel, int index)         {             _panel = panel;             _index = index;         }          wrappanelabstraction _panel;          public readonly int _index;          int _sectionindex = -1;         public int sectionindex         {                         {                 if (_sectionindex == -1)                 {                     return _index % _panel._averageitemspersection - 1;                 }                 return _sectionindex;             }             set             {                 if (_sectionindex == -1)                     _sectionindex = value;             }         }          int _section = -1;         public int section         {                         {                 if (_section == -1)                 {                     return _index / _panel._averageitemspersection;                 }                 return _section;             }             set             {                 if (_section == -1)                     _section = value;             }         }     }      class wrappanelabstraction : ienumerable<itemabstraction>     {         public wrappanelabstraction(int itemcount)         {             list<itemabstraction> items = new list<itemabstraction>(itemcount);             (int = 0; < itemcount; i++)             {                 itemabstraction item = new itemabstraction(this, i);                 items.add(item);             }              items = new readonlycollection<itemabstraction>(items);             _averageitemspersection = itemcount;             _itemcount = itemcount;         }          public readonly int _itemcount;         public int _averageitemspersection;         private int _currentsetsection = -1;         private int _currentsetitemindex = -1;         private int _itemsincurrentsecction = 0;         private object _syncroot = new object();          public int sectioncount         {                         {                 int ret = _currentsetsection + 1;                 if (_currentsetitemindex + 1 < items.count)                 {                     int itemsleft = items.count - _currentsetitemindex;                     ret += itemsleft / _averageitemspersection + 1;                 }                 return ret;             }         }          private readonlycollection<itemabstraction> items { get; set; }          public void setitemsection(int index, int section)         {             lock (_syncroot)             {                 if (section <= _currentsetsection + 1 && index == _currentsetitemindex + 1)                 {                     _currentsetitemindex++;                     items[index].section = section;                     if (section == _currentsetsection + 1)                     {                         _currentsetsection = section;                         if (section > 0)                         {                             _averageitemspersection = (index) / (section);                         }                         _itemsincurrentsecction = 1;                     }                     else                         _itemsincurrentsecction++;                     items[index].sectionindex = _itemsincurrentsecction - 1;                 }             }         }          public itemabstraction this[int index]         {             { return items[index]; }         }          #region ienumerable<itemabstraction> members          public ienumerator<itemabstraction> getenumerator()         {             return items.getenumerator();         }          #endregion          #region ienumerable members          system.collections.ienumerator system.collections.ienumerable.getenumerator()         {             return getenumerator();         }          #endregion     }      #endregion } 

i had similar problem custom panel implemetning iscrollinfo. in implementation background not moving @ (i think background moves because setting rendertransform). ended manually updating viewport on assigned brush in sethorizontaloffset/setverticaloffset this:

    public void sethorizontaloffset(double offset)     {                offsetx_ = offset;         ((tilebrush)background).viewport = new rect(-offsetx_, -offsety_, width_, height_);         ((tilebrush)background).viewportunits = brushmappingmode.absolute;     } 

you first need set viewboxunits = brushmappingmode.absolute on brush item.


Comments

Popular posts from this blog

javascript - DIV "hiding" when changing dropdown value -

Does Firefox offer AppleScript support to get URL of windows? -

android - How to install packaged app on Firefox for mobile? -